windows监视内存读写

memexcept.c

#define _WIN32_WINNT 0x500
#include<windows.h>
#include"memexcept.h"
#define roundup(x,n) (((x)+((n)-1))&(~((n)-1)))
#define rounddown(x,n) ((x)&(~((n)-1)))
#define BusyWait(x) while(InterlockedCompareExchange((void**)&(x),0,0))SwitchToThread()
#define Acquire(x) while(InterlockedExchange(&(x),1))SwitchToThread()
#define Release(x) InterlockedExchange(&(x),0)
typedef PVOID(WINAPI*PAddVectoredExceptionHandler)(ULONG FirstHandler,PVOID VectoredHandler);
typedef ULONG(WINAPI*PRemoveVectoredExceptionHandler)(PVOID Handler);
static PAddVectoredExceptionHandler pAddVectoredExceptionHandler=0;
static PRemoveVectoredExceptionHandler pRemoveVectoredExceptionHandler=0;


typedef struct _ADDRRANGE
{
	struct _ADDRRANGE*Next,*Previous;
	char*ProtectStart,*ProtectEnd,*WatchStart,*WatchEnd;
	DWORD OldProtect;
	PMemoryWatchCallback Callback;
	BOOL NotifyAfterRead:1,NotifyAfterWrite:1,Pending:1,Enabled:1,IsWrite:1;
	void*Address;
	UINT_PTR Tag;
	CRITICAL_SECTION CriticalSection;
}ADDRRANGE,*PADDRRANGE;

static SYSTEM_INFO SystemInfo;
static PVOID HandlerHandle=0,RangeHeap=0;
static PADDRRANGE RangeListHead=0;
static LONG RangeListRead=0,RangeListWrite=0;

BOOL CanRead(void*Address)
{
	__try
	{
		*(volatile char*)Address;
		return TRUE;
	}__except(EXCEPTION_EXECUTE_HANDLER)
	{
		return FALSE;
	}
}

BOOL CanWrite(void*Address)
{
	__try
	{
		*(volatile char*)Address=*(volatile char*)Address;
		return TRUE;
	}__except(EXCEPTION_EXECUTE_HANDLER)
	{
		return FALSE;
	}
}

HANDLE RegisterMemoryWatcher(PVOID BaseAddress,SIZE_T Length,PMemoryWatchCallback Callback,BOOL NotifyAfterRead,BOOL NotifyAfterWrite,UINT_PTR Tag)
{
	PADDRRANGE range;
	range=HeapAlloc(RangeHeap,0,sizeof(ADDRRANGE));
	if(range)
	{
		range->Previous=0;
		range->Next=RangeListHead;
		range->WatchStart=(char*)BaseAddress;
		range->WatchEnd=(char*)BaseAddress+Length;
		range->ProtectStart=(char*)rounddown((SIZE_T)BaseAddress,SystemInfo.dwPageSize);
		range->ProtectEnd=(char*)roundup((SIZE_T)BaseAddress+Length,SystemInfo.dwPageSize);
		range->Callback=Callback;
		range->NotifyAfterRead=NotifyAfterRead;
		range->NotifyAfterWrite=NotifyAfterWrite;
		range->Pending=0;
		range->Enabled=1;
		range->Tag=Tag;
		InitializeCriticalSection(&range->CriticalSection);
		if(VirtualProtectEx(GetCurrentProcess(),BaseAddress,Length,PAGE_NOACCESS,&range->OldProtect))
		{
			if(RangeListHead)
				RangeListHead->Previous=range;
			RangeListHead=range;
			return (HANDLE)range;
		}else
		{
			DeleteCriticalSection(&range->CriticalSection);
			HeapFree(RangeHeap,0,range);
		}
	}
	return NULL;
}

VOID UnregisterMemoryWatcher(HANDLE Handle)
{
	PADDRRANGE range;
	if(Handle)
	{
		range=(PADDRRANGE)Handle;
		VirtualProtectEx(GetCurrentProcess(),range->WatchStart,range->WatchEnd-range->WatchStart,range->OldProtect,&range->OldProtect);
		Acquire(RangeListWrite);
		BusyWait(RangeListRead);
		if(range->Previous)
			range->Previous->Next=range->Next;
		if(range->Next)
			range->Next->Previous=range->Previous;
		DeleteCriticalSection(&range->CriticalSection);
		HeapFree(RangeHeap,0,range);
		Release(RangeListWrite);
	}
}

VOID EnableMemoryWatcher(HANDLE Handle,BOOL Enable)
{
	PADDRRANGE range;
	if(Handle)
	{
		DWORD OldProtect;
		range=(PADDRRANGE)Handle;
		if(range->Enabled=Enable)
			VirtualProtectEx(GetCurrentProcess(),range->WatchStart,range->WatchEnd-range->WatchStart,PAGE_NOACCESS,&OldProtect);
		else VirtualProtectEx(GetCurrentProcess(),range->WatchStart,range->WatchEnd-range->WatchStart,range->OldProtect,&OldProtect);
	}
}

LONG CALLBACK MemExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
{
	PEXCEPTION_RECORD ExceptionRecord;PCONTEXT Context;
	ExceptionRecord=ExceptionInfo->ExceptionRecord;
	Context=ExceptionInfo->ContextRecord;
	if(ExceptionRecord->ExceptionCode==EXCEPTION_ACCESS_VIOLATION)
	{
		PADDRRANGE range;DWORD OldProtect;BOOLEAN Pending,Found=0;
		char*addr=(char*)ExceptionRecord->ExceptionInformation[1];
		Acquire(RangeListWrite);
		InterlockedIncrement(&RangeListRead);
		Release(RangeListWrite);
		for(range=RangeListHead;range;range=range->Next)
		{
			if(addr>=range->ProtectStart&&addr<range->ProtectEnd)
			{
				EnterCriticalSection(&range->CriticalSection);
				VirtualProtectEx(GetCurrentProcess(),range->WatchStart,range->WatchEnd-range->WatchStart,range->OldProtect,&OldProtect);
				Found=1;
				if(addr>=range->WatchStart&&addr<range->WatchEnd&&range->Enabled)
				{
					range->IsWrite=(ExceptionRecord->ExceptionInformation[0]==1);
					range->Address=addr;
					if((!range->NotifyAfterRead&&!range->IsWrite)||(!range->NotifyAfterWrite&&range->IsWrite))
						if(range->Callback(range->Address,range->IsWrite,&range->Tag))
						{
							range->Enabled=0;
							LeaveCriticalSection(&range->CriticalSection);
							range->Pending=0;
							continue;
						}
					range->Pending=1;
					Pending=1;
				}
			}
		}
		InterlockedDecrement(&RangeListRead);
		if(Pending)Context->EFlags|=256;
		return Found?EXCEPTION_CONTINUE_EXECUTION:EXCEPTION_CONTINUE_SEARCH;
	}else if(ExceptionRecord->ExceptionCode==EXCEPTION_SINGLE_STEP)
	{
		PADDRRANGE range;DWORD OldProtect;
		Acquire(RangeListWrite);
		InterlockedIncrement(&RangeListRead);
		Release(RangeListWrite);
		for(range=RangeListHead;range;range=range->Next)
			if(range->Pending)
			{
				if((range->NotifyAfterRead&&!range->IsWrite)||(range->NotifyAfterWrite&&range->IsWrite))
					range->Enabled=!range->Callback(range->Address,range->IsWrite,&range->Tag);
				VirtualProtectEx(GetCurrentProcess(),range->WatchStart,range->WatchEnd-range->WatchStart,PAGE_NOACCESS,&OldProtect);
				LeaveCriticalSection(&range->CriticalSection);
				range->Pending=0;
			}
		InterlockedDecrement(&RangeListRead);
		return EXCEPTION_CONTINUE_EXECUTION;
	}
	return EXCEPTION_CONTINUE_SEARCH;
}

BOOL StartupMemExcept(void)
{
	GetSystemInfo(&SystemInfo);
	RangeHeap=HeapCreate(0,0,0);
	if(!pAddVectoredExceptionHandler)
		pAddVectoredExceptionHandler=(PAddVectoredExceptionHandler)GetProcAddress(GetModuleHandleW(L"kernel32.dll"),"AddVectoredExceptionHandler");
	if(pAddVectoredExceptionHandler)
		HandlerHandle=pAddVectoredExceptionHandler((ULONG)-1,MemExceptionHandler);
	return HandlerHandle!=0;
}

BOOL CleanupMemExcept(void)
{
	BOOL r=FALSE;
	if(!pRemoveVectoredExceptionHandler)
		pRemoveVectoredExceptionHandler=(PRemoveVectoredExceptionHandler)GetProcAddress(GetModuleHandleW(L"kernel32.dll"),"RemoveVectoredExceptionHandler");
	if(pRemoveVectoredExceptionHandler)
		r=pRemoveVectoredExceptionHandler(HandlerHandle);
	if(r)
	{
		PADDRRANGE range;
		Acquire(RangeListWrite);
		BusyWait(RangeListRead);	
		for(range=RangeListHead;range;range=range->Next)
			VirtualProtectEx(GetCurrentProcess(),range->WatchStart,range->WatchEnd-range->WatchStart,range->OldProtect,&range->OldProtect);
		for(range=RangeListHead;range;range=range->Next)
		{
			DeleteCriticalSection(&range->CriticalSection);
		}
		HeapDestroy(RangeHeap);
		Release(RangeListWrite);
		RangeListHead=0;
		RangeHeap=0;
	}
	return r;
}


memexcept.h

typedef int(CALLBACK*PMemoryWatchCallback)(void*Address,BOOL Write,UINT_PTR*Tag);

#ifdef __cplusplus
extern"C"{
#endif


extern BOOL CanRead(void*Address);
extern BOOL CanWrite(void*Address);
extern BOOL StartupMemExcept(void);
extern BOOL CleanupMemExcept(void);
extern HANDLE RegisterMemoryWatcher(PVOID BaseAddress,SIZE_T Length,PMemoryWatchCallback Callback,BOOL NotifyAfterRead,BOOL NotifyAfterWrite,UINT_PTR Tag);
extern VOID UnregisterMemoryWatcher(HANDLE Handle);
extern VOID EnableMemoryWatcher(HANDLE Handle,BOOL Enable);



#ifdef __cplusplus
}
#endif


main.cpp

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

int CALLBACK cb(void*addr,BOOL w,UINT_PTR*Tag)
{
	int*p=(int*)addr;
	printf("address:%p,write:%d,value:%d\n",p,w,CanRead(&p)?*p:0);
	return 0;//return 1 to disable watcher
}

int main()
{
	int(*p)[4];
	p=(int(*)[4])VirtualAlloc(0,sizeof(*p),MEM_COMMIT,PAGE_READWRITE);
	(*p)[0]=0;
	(*p)[1]=1;
	(*p)[2]=2;
	StartupMemExcept();//initialize
	RegisterMemoryWatcher(p,sizeof(*p),cb,FALSE,TRUE,0);
	printf("v:%d\n",(*p)[0]);
	printf("v:%d\n",(*p)[1]);
	puts("dd");
__try
{
	printf("v:%d\n",(*p)[2]);
	(*p)[3]=6;
	*(volatile char*)0;//not watched
}__except(EXCEPTION_EXECUTE_HANDLER)
{
	puts("except");
}
	CleanupMemExcept();//cleanup
	return 0;
}

http://download.csdn.net/detail/lactoferrin/4091105

你可能感兴趣的:(windows,exception,search,callback,winapi,Pointers)