更安全的MmIsAddressValid

代码来着开源工具

CheatEngine


在初始化是先调用InitMemSafe()

然后就可以使用IsAddressSafe来代替MmIsAddressValid了

int PTESize;
UINT_PTR PAGE_SIZE_LARGE;
UINT_PTR MAX_PDE_POS;
UINT_PTR MAX_PTE_POS;

struct PTEStruct
{
	unsigned P         :  1; // present (1 = present)
	unsigned RW        :  1; // read/write
	unsigned US        :  1; // user/supervisor
	unsigned PWT       :  1; // page-level write-through
	unsigned PCD       :  1; // page-level cache disabled
	unsigned A         :  1; // accessed
	unsigned Reserved  :  1; // dirty
	unsigned PS        :  1; // page size (0 = 4-KB page)
	unsigned G         :  1; // global page
	unsigned A1		   :  1; // available 1 aka copy-on-write
	unsigned A2		   :  1; // available 2/ is 1 when paged to disk
	unsigned A3		   :  1; // available 3
	unsigned PFN       : 20; // page-frame number
};

void InitMemSafe()
{
#ifndef AMD64
	ULONG cr4reg;
    //determine if PAE is used
	cr4reg=(ULONG)__readcr4();
	if ((cr4reg & 0x20)==0x20)
	{
		PTESize=8; //pae
		PAGE_SIZE_LARGE=0x200000;
		MAX_PDE_POS=0xC0604000;
		MAX_PTE_POS=0xC07FFFF8;
	}
	else
	{
		PTESize=4;
		PAGE_SIZE_LARGE=0x400000;
		MAX_PDE_POS=0xC0301000;
		MAX_PTE_POS=0xC03FFFFC;
	}
#else
	PTESize=8; //pae
	PAGE_SIZE_LARGE=0x200000;
	MAX_PTE_POS=0xFFFFF6FFFFFFFFF8ULL;
	MAX_PDE_POS=0xFFFFF6FB7FFFFFF8ULL;
#endif
}

BOOLEAN IsAddressSafe(UINT_PTR StartAddress)
{
	#ifdef AMD64
	//cannonical check. Bits 48 to 63 must match bit 47
	UINT_PTR toppart=(StartAddress >> 47);
	if (toppart & 1)
	{
		//toppart must be 0x1ffff
		if (toppart != 0x1ffff)
			return FALSE;
	}
	else
	{
		//toppart must be 0
		if (toppart != 0)
			return FALSE;

	}
	#endif
	//PDT+PTE judge
	{
	#ifdef AMD64
		UINT_PTR kernelbase=0x7fffffffffffffffULL;
		if (StartAddress<kernelbase)
		{
			return TRUE;
		}
		else
		{
			PHYSICAL_ADDRESS physical;
			physical.QuadPart=0;
			physical=MmGetPhysicalAddress((PVOID)StartAddress);
			return (physical.QuadPart!=0);
		}
		return TRUE; //for now untill I ave figure out the win 4 paging scheme
	#else
		ULONG kernelbase=0x7ffe0000;
		UINT_PTR PTE,PDE;
		struct PTEStruct *x;
		if (StartAddress<kernelbase)
		{
			return TRUE;
		}
		PTE=(UINT_PTR)StartAddress;
		PTE=PTE/0x1000*PTESize+0xc0000000;
		//now check if the address in PTE is valid by checking the page table directory at 0xc0300000 (same location as CR3 btw)
		PDE=PTE/0x1000*PTESize+0xc0000000; //same formula
		x=(struct PTEStruct *)PDE;
		if ((x->P==0) && (x->A2==0))
		{
			//Not present or paged, and since paging in this area isn't such a smart thing to do just skip it
			//perhaps this is only for the 4 mb pages, but those should never be paged out, so it should be 1
			//bah, I've got no idea what this is used for
			return FALSE;
		}
		if (x->PS==1)
		{
			//This is a 4 MB page (no pte list)
			//so, (startaddress/0x400000*0x400000) till ((startaddress/0x400000*0x400000)+(0x400000-1) ) ) is specified by this page
		}
		else //if it's not a 4 MB page then check the PTE
		{
			//still here so the page table directory agreed that it is a usable page table entry
			x=(PVOID)PTE;
			if ((x->P==0) && (x->A2==0))
				return FALSE; //see for explenation the part of the PDE
		}
		return TRUE;
	#endif
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值