欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[分享]调戏:海森堡原理内存访问检测的梗

[分享]调戏:海森堡原理内存访问检测的梗

名字高大上的梗,其实如果知道了具体原因就会觉得很简单。
首先说一下 海森堡原理是什么
从百度百科可以得知
http://baike.baidu.com/view/24947.htm
海森堡原理就是如果测量某个参数必然导致其他参数被改变。
那么当调试器存在时,会改变那些事情呢?
这里不得不提到一个古老的掉渣的东西就是PAGE_GUARD属性。
当任意一个内存页属性被设置上PAGE_GUARD时,
访问该页会抛出一个异常,并消除PAGE_GUARD属性。
但是如果是调试器或者其他进程使用API去访问内存的时候,
不会触发进程内部异常,而且访问后,该属性就会消失。
于是有一种奇葩的逻辑就诞生了。
实现方式:
1.设置一个异常扑捉(VEH或者HOOK)。
2.遍历指定模块的内存分布(块状分布,其实可以直接对整个模块做处理,效率都差不多)。
3.对指定模块的内存进行设置PAGE_GUARD。
4.异常中处理PAGE_GUARD异常的并做标记
5.定时检查指定模块的内存是否PAGE_GUARD属性被去除和重新设置PAGE_GUARD,
如果被去除,则判断是否正常的异常,不是则退出进程。


#include "stdafx.h"

#include <windows.h>

#include <list>

#include "ntdll.h"

typedef struct _MAD_MEM_

{

	MEMORY_BASIC_INFORMATION mbi;

	BOOL bAccess;

}MAD_MEM,*PMAD_MEM;

typedef ULONG (WINAPI *pfnRtlDispatchException)(PEXCEPTION_RECORD pExcptRec,CONTEXT * pContext);

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

BOOL RtlDispatchException(PEXCEPTION_RECORD pExcptRec,CONTEXT * pContext);

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

static pfnRtlDispatchException m_fnRtlDispatchException=NULL;

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

BOOL g_bHook	= FALSE;

std::list<PMAD_MEM> memoryBlocks;

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

ULONG WINAPI _RtlDispatchException( PEXCEPTION_RECORD pExcptRec,CONTEXT * pContext )

{

	if(RtlDispatchException(pExcptRec,pContext)) return 1;

	return m_fnRtlDispatchException(pExcptRec,pContext);

}

VOID InstallMemAccessDetect()

{

	BYTE *pAddr=(BYTE *)::GetProcAddress(::GetModuleHandleA("ntdll.dll"),"KiUserExceptionDispatcher");

	if (g_bHook)

	{

		return;

	}

	if (pAddr)

	{

		while (*pAddr!=0xE8)pAddr++; 

		m_fnRtlDispatchException=(pfnRtlDispatchException)((*(DWORD *)(pAddr+1))+5+(DWORD)pAddr);  

		DWORD dwNewAddr=(DWORD)_RtlDispatchException-(DWORD)pAddr-5;           

		DWORD dwOld;

		VirtualProtect((LPVOID)pAddr,0x1000,PAGE_EXECUTE_READWRITE,&dwOld);

		RtlCopyMemory((PVOID)((DWORD)pAddr+1),(PVOID)&dwNewAddr,4);  

		g_bHook=TRUE;

	}

}

DWORD WINAPI MADThread(LPVOID Param)

{

	std::list<PMAD_MEM>::iterator b;

	for (b = memoryBlocks.begin(); b != memoryBlocks.end(); b++)

	{

		DWORD dwOld;

		PMAD_MEM m_Block = *b;

		m_Block->bAccess=FALSE;

		*b=m_Block;

		VirtualProtect(m_Block->mbi.BaseAddress,

			m_Block->mbi.RegionSize,

			m_Block->mbi.Protect|PAGE_GUARD,

			&dwOld);

	}

	while (1)

	{

		std::list<PMAD_MEM>::iterator b;

		for (b = memoryBlocks.begin(); b != memoryBlocks.end(); b++)

		{

			DWORD dwOld;

			PMAD_MEM m_Block = *b;

			MEMORY_BASIC_INFORMATION mbi;

			VirtualQueryEx(GetCurrentProcess(),

				m_Block->mbi.BaseAddress,

				&mbi,

				sizeof(mbi));

			if ((mbi.Protect&PAGE_GUARD)!=PAGE_GUARD)

			{

				if (!m_Block->bAccess)

				{

					//发生了外部内存访问!

					ExitProcess(-1);

				}

			}

			m_Block->bAccess=FALSE;

			*b=m_Block;

			VirtualProtect(m_Block->mbi.BaseAddress,

				m_Block->mbi.RegionSize,

				m_Block->mbi.Protect|PAGE_GUARD,

				&dwOld);

		}

		Sleep(1000*30);

	}

}

VOID InitMAD()

{

	MEMORY_BASIC_INFORMATION meminfo;

	unsigned char *addr = 0;

	unsigned char *endaddr =0;

	DWORD totalBytes = 0;

	InstallMemAccessDetect();

	VirtualQuery((LPCVOID)GetModuleHandleA("game.dll"),&meminfo,sizeof(meminfo));

	addr = (unsigned char *)meminfo.AllocationBase;

	endaddr = addr + RtlImageNtHeader(addr)->OptionalHeader.SizeOfImage;

	while (addr<endaddr)

	{

		if (!VirtualQueryEx(GetCurrentProcess(), addr, &meminfo, sizeof(meminfo)))

			break;

		bool Commited = meminfo.State & MEM_COMMIT;

		bool Readable = meminfo.Protect & (PAGE_READWRITE |PAGE_READONLY);

		bool Guarded = meminfo.Protect & PAGE_GUARD;

		if (Commited && Readable && !Guarded)

		{

			totalBytes += (DWORD)meminfo.RegionSize;

			PMAD_MEM pNew = new MAD_MEM;

			pNew->mbi = meminfo;

			pNew->bAccess = FALSE;

			memoryBlocks.push_back(pNew);

		}

		addr = (unsigned char*)meminfo.BaseAddress + meminfo.RegionSize;

	}

	CreateThread(NULL,0,

		MADThread,NULL,

		0,NULL);

}

BOOL RtlDispatchException(PEXCEPTION_RECORD pExcptRec,CONTEXT * pContext)

{

	ULONG_PTR Eip = (ULONG_PTR)pExcptRec->ExceptionAddress;

	if (!memoryBlocks.empty() && pExcptRec->ExceptionCode == EXCEPTION_GUARD_PAGE)

	{		

		std::list<PMAD_MEM>::iterator b;

		for (b = memoryBlocks.begin(); b != memoryBlocks.end(); b++)

		{

				PMAD_MEM m_Block = *b;

				if (Eip>=(ULONG_PTR)m_Block->mbi.BaseAddress

					&& Eip<=(ULONG_PTR)m_Block->mbi.BaseAddress+m_Block->mbi.RegionSize)

				{

					m_Block->bAccess =TRUE;

					*b = m_Block;

					return TRUE;

				}

		}

	}

	return FALSE;

}

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功