首页
社区
课程
招聘
[求助]内核地址有效,内容无效不知道怎么搞,大神求助。
发表于: 2016-8-12 16:51 5497

[求助]内核地址有效,内容无效不知道怎么搞,大神求助。

2016-8-12 16:51
5497
在WIn10系统下遇到一个内核地址检测是有效的,内容是无效的情况,
使用了ProbeForRead函数与MmIsAddressValid,没起到效果,使用ProbeForRead函数,显示每一个地址都是错的,使用MmIsAddressValid的时候,检测地址是有效的,进入流程解析机器码的时候又不错了。

[课程]Linux pwn 探索篇!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (9)
雪    币: 13
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
进入流程解析机器码的时候又错了,无法解析。
2016-8-12 16:52
0
雪    币: 2291
活跃值: (933)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
3
你用之前还是查一下WDK中ProbeForRead的用法啊!

The ProbeForRead routine checks that a user-mode buffer actually resides in the user portion of the address space, and is correctly aligned.
2016-8-12 17:06
0
雪    币: 13
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
话说这样的问题该怎么解决啊
2016-8-12 17:11
0
雪    币: 522
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
代码  明明检测的是一个地址   
但你在接下来的判断语句中  直接读了 这个地址+N的内存        很多情况下  这样的代码可以正常运行  
但逻辑上 明显是错误的。
2016-8-12 17:50
0
雪    币: 19
活跃值: (1086)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
以下摘自A-Protect源码

c文件

#include "FuncAddrValid.h"

__inline ULONG CR4()
{
	// mov eax, cr4
	__asm _emit 0x0F __asm _emit 0x20 __asm _emit 0xE0
}
BOOLEAN
	MmIsSystemAddressAccessable(
	PVOID VirtualAddress
	)

	/*++

	Routine Description

	For a given virtual address this function returns TRUE if the address
	is accessable without an access violation (it may incur a page fault).

	Arguments

	VirtualAddress

	Address to be checked

	Return value

	TRUE if address may be safely accessed, FALSE otherwise

	--*/

{
	if (CR4() & PAE_ON)
	{
		PMMPTE_PAE PointerPte;

		PointerPte = MiGetPdeAddressPae (VirtualAddress);
		if ((PointerPte->u.Long.QuadPart == MM_ZERO_PTE) ||
			(PointerPte->u.Long.QuadPart == MM_ZERO_KERNEL_PTE) ||
			(PointerPte->u.Soft.Protection == MM_ZERO_ACCESS)) 
		{
			return FALSE;
		}

		PointerPte = MiGetPteAddressPae (VirtualAddress);
		if ((PointerPte->u.Long.QuadPart == MM_ZERO_PTE) ||
			(PointerPte->u.Long.QuadPart == MM_ZERO_KERNEL_PTE) ||
			(PointerPte->u.Soft.Protection == MM_ZERO_ACCESS)) 
		{
			return FALSE;
		}
	}
	else
	{
		PMMPTE PointerPte;

		PointerPte = MiGetPdeAddress (VirtualAddress);
		if ((PointerPte->u.Long == MM_ZERO_PTE) ||
			(PointerPte->u.Long == MM_ZERO_KERNEL_PTE) ||
			(PointerPte->u.Soft.Protection == MM_ZERO_ACCESS)) 
		{
			return FALSE;
		}

		PointerPte = MiGetPteAddress (VirtualAddress);
		if ((PointerPte->u.Long == MM_ZERO_PTE) ||
			(PointerPte->u.Long == MM_ZERO_KERNEL_PTE) ||
			(PointerPte->u.Soft.Protection == MM_ZERO_ACCESS)) 
		{
			return FALSE;
		}
	}

	return TRUE;
}

#if 0
extern "C" extern ULONG KiBugCheckData;

VOID MmAllowPageFaultsAtRaisedIrql ()
	/**
	Allow page faults at raised IRQL
	*/
{
	//
	// KiTrap0E performs check if KiBugCheckData == 0.
	// If so, KiTrap0E calls KeBugCheckEx(IRQL_NOT_LESS_OR_EQUAL,...)
	//  if not, it calls MmAccessFault and resolves fault.
	//

	KiBugCheckData = 0xFFFFFFFF;
}

VOID MmForbidPageFaultsAtRaisedIrql ()
{
	KiBugCheckData = 0;
}
#endif

// Irql < DISPATCH_LEVEL
VOID MmMakeAddressWritable (PVOID VirtualAddress, BOOLEAN Write)
{
	PMMPTE_PAE PointerPte_Pae;
	PMMPTE PointerPte;
	ULONG t;

	ASSERT (MmIsSystemAddressAccessable(VirtualAddress));

	// load page
	t = *(ULONG*)VirtualAddress;

	// make it writable
	if (CR4() & PAE_ON)
	{
		PointerPte_Pae = MiGetPteAddressPae (VirtualAddress);
		PointerPte_Pae->u.Hard.Write = Write;
	}
	else
	{
		PointerPte = MiGetPteAddress (VirtualAddress);
		PointerPte->u.Hard.Valid = Write;
	}
}

PMDL LockMem(PVOID Buffer, ULONG Size)
{
	PMDL Mdl;
	ULONG i;

	Mdl = IoAllocateMdl (Buffer, Size, FALSE, FALSE, NULL);
	if (Mdl)
	{
		//KdPrint(("LOCKMEM: Mdl allocated at %X\n", Mdl));

		__try
		{
			for (i=0; i<Size; i++)
			{
				((UCHAR*)Buffer)[i] = ((UCHAR*)Buffer)[i];
			}

			KdPrint (("LOCKMEM: Loaded pages\n"));

			MmProbeAndLockPages (Mdl, KernelMode, IoWriteAccess);

			KdPrint (("LOCKMEM: Mdl probed and locked\n"));
		}
		__except (EXCEPTION_EXECUTE_HANDLER)
		{
			IoFreeMdl (Mdl);
			//KdPrint(("LockMem: MmProbeAndLock pages failed with exception code %X\n", GetExceptionCode()));
			return NULL;
		}

		return Mdl;
	}

	//KdPrint(("LockMem: IoAllocateMdl failed\n"));
	return NULL;
}


VOID UnlockMem (PMDL Mdl)
{
	MmUnlockPages (Mdl);
	IoFreeMdl (Mdl);
}
VALIDITY_CHECK_STATUS MmIsAddressValidExNotPae(
	IN PVOID Pointer
	)
{
	VALIDITY_CHECK_STATUS  Return = VCS_INVALID;
	MMPTE* Pde;
	MMPTE* Pte;
	MMPTE pte;

	Pde = MiGetPdeAddress(Pointer);

	//KdPrint(("PDE is 0x%08x\n", Pde));
	if( Pde->u.Hard.Valid )
	{
		//KdPrint(("PDE entry is valid, PTE PFN=%08x\n", Pde->u.Hard.PageFrameNumber));

		Pte = MiGetPteAddress(Pointer);

		//KdPrint(("PTE is 0x%08x\n", Pte));
		if( Pte->u.Hard.Valid )
		{
			//KdPrint(("PTE entry is valid, PFN=%08x\n", Pte->u.Hard.PageFrameNumber));
			Return = VCS_VALID;
		}
		else
		{
			//
			// PTE is not valid
			//

			pte = *Pte;

			//KdPrint(("Got invalid PTE [%08x]: Proto=%d,Transition=%d,Protection=0x%x,PageFilePFN=0x%x\n",
			//	pte.u.Long,
			//	pte.u.Soft.Prototype,
			//	pte.u.Soft.Transition,
			//	pte.u.Soft.Protection,
			//	pte.u.Soft.PageFileHigh));

			if( pte.u.Long )
			{
				if( pte.u.Soft.Prototype == 1 )
				{
					//KdPrint(("PTE entry is not valid, points to prototype PTE.\n"));

					// more accurate check should be performed here for pointed prototype PTE!

					Return = VCS_PROTOTYPE;
				}
				else  // not a prototype PTE
				{
					if( pte.u.Soft.Transition != 0 )
					{
						//
						// This is a transition page. Consider it invalid.
						//

						//KdPrint(("PTE entry is not valid, points to transition page.\n"));

						Return = VCS_TRANSITION;
					}
					else if (pte.u.Soft.PageFileHigh == 0)
					{
						//
						// Demand zero page
						//

						//KdPrint(("PTE entry is not valid, points to demand-zero page.\n"));

						Return = VCS_DEMANDZERO;
					}
					else
					{
						//
						// Pagefile PTE
						//

						if( pte.u.Soft.Transition == 0 )
						{
							//KdPrint(("PTE entry is not valid, VA is paged out (PageFile offset=%08x)\n",
							//	pte.u.Soft.PageFileHigh));

							Return = VCS_PAGEDOUT;
						}
						else
						{
							//KdPrint(("PTE entry is not valid, Refault\n"));
						}
					}
				}
			}
			else
			{
				//KdPrint(("PTE entry is completely invalid\n"));
			}
		}
	}
	else
	{
		//KdPrint(("PDE entry is not valid\n"));
	}

	return Return;
}
VALIDITY_CHECK_STATUS MmIsAddressValidExPae(
	IN PVOID Pointer
	)
{
	VALIDITY_CHECK_STATUS Return = VCS_INVALID;
	MMPTE_PAE* Pde;
	MMPTE_PAE* Pte;
	MMPTE_PAE pte;

	Pde = MiGetPdeAddressPae(Pointer);

	//KdPrint(("PDE is at 0x%08x\n", Pde));
	if( Pde->u.Hard.Valid )
	{
		//KdPrint(("PDE entry is valid, PTE PFN=%08x\n", Pde->u.Hard.PageFrameNumber));

		if( Pde->u.Hard.LargePage != 0 )
		{
			//
			// This is a large 2M page
			//

			//KdPrint(("! PDE points to large 2M page\n"));

			Pte = Pde;
		}
		else
		{
			//
			// Small 4K page
			//

			// Get its PTE
			Pte  = MiGetPteAddressPae(Pointer);
		}

		//KdPrint(("PTE is at 0x%08x\n", Pte));
		if( Pte->u.Hard.Valid )
		{
			//KdPrint(("PTE entry is valid, PFN=%08x\n", Pte->u.Hard.PageFrameNumber));

			Return = VCS_VALID;
		}
		else
		{
			//
			// PTE is not valid
			//

			pte = *Pte;

			//KdPrint(("Got invalid PTE [%08x%08x]\n", pte.u.Long.HighPart, pte.u.Long.LowPart));

			if( pte.u.Long.LowPart == 0 )
			{
				//KdPrint(("PTE entry is completely invalid (page is not committed or is within VAD tree)\n"));
			}
			else
			{
				if( pte.u.Soft.Prototype == 1 )
				{
					// 					//KdPrint(("PTE entry is not valid, points to prototype PTE. Protection=%x[%s], ProtoAddress=%x\n",
					// 						(ULONG)pte.u.Proto.Protection,
					// 						MiPageProtectionString((UCHAR)pte.u.Proto.Protection),
					// 						(ULONG)pte.u.Proto.ProtoAddress));

					// more accurate check should be performed here for pointed prototype PTE!

					Return = VCS_PROTOTYPE;
				}
				else  // not a prototype PTE
				{
					if( pte.u.Soft.Transition != 0 )
					{
						//
						// This is a transition page.
						//

						// 						//KdPrint(("PTE entry is not valid, points to transition page. PFN=%x, Protection=%x[%s]\n",
						// 							(ULONG)pte.u.Trans.PageFrameNumber,
						// 							(ULONG)pte.u.Trans.Protection,
						// 							MiPageProtectionString((UCHAR)pte.u.Trans.Protection)));

						Return = VCS_TRANSITION;
					}
					else if (pte.u.Soft.PageFileHigh == 0)
					{
						//
						// Demand zero page
						//

						// 						//KdPrint(("PTE entry is not valid, points to demand-zero page. Protection=%x[%s]\n",
						// 							(ULONG)pte.u.Soft.Protection,
						// 							MiPageProtectionString((UCHAR)pte.u.Soft.Protection)));

						Return = VCS_DEMANDZERO;
					}
					else
					{
						//
						// Pagefile PTE
						//

						if( pte.u.Soft.Transition == 0 )
						{
							// 							//KdPrint(("PTE entry is not valid, VA is paged out. PageFile Offset=%08x, Protection=%x[%s]\n",
							// 								(ULONG)pte.u.Soft.PageFileHigh,
							// 								(ULONG)pte.u.Soft.Protection,
							// 								MiPageProtectionString((UCHAR)pte.u.Soft.Protection)));

							Return = VCS_PAGEDOUT;
						}
						else
						{
							//KdPrint(("PTE entry is not valid, Refault\n"));
						}
					}
				}
			}
		}
	}
	else
	{
		//KdPrint(("PDE entry is not valid\n"));
	}

	return Return;
}
VALIDITY_CHECK_STATUS MiIsAddressValidEx(
	IN PVOID Pointer
	)
{
	if( CR4() & PAE_ON ) {
		return MmIsAddressValidExPae(Pointer);
	}
	else {
		return MmIsAddressValidExNotPae(Pointer);
	}
}
BOOL MmIsAddressValidEx(
	IN PVOID Pointer
	)
{
	VALIDITY_CHECK_STATUS MmRet;
	ULONG ulTry;

	if (!ARGUMENT_PRESENT(Pointer) ||
		!Pointer){
		return FALSE;
	}
	/*
	//VCS_TRANSITION、VCS_PAGEDOUT内存居然是这样子~~擦~

	lkd> dd f8ad5ad8
	f8ad5ad8  ???????? ???????? ???????? ????????
	f8ad5ae8  ???????? ???????? ???????? ????????
	f8ad5af8  ???????? ???????? ???????? ????????
	f8ad5b08  ???????? ???????? ???????? ????????
	f8ad5b18  ???????? ???????? ???????? ????????
	f8ad5b28  ???????? ???????? ???????? ????????
	f8ad5b38  ???????? ???????? ???????? ????????
	f8ad5b48  ???????? ???????? ???????? ????????
	*/
	MmRet = MiIsAddressValidEx(Pointer);
	if (MmRet != VCS_VALID){
		return FALSE;
	}
	return TRUE;
}
BOOL MmIsAddressRangeValid(
	IN PVOID Address,
	IN ULONG Size
	)
{
	ULONG Ptr = 0;
	VALIDITY_CHECK_STATUS MmRet;

	for(Ptr =  (ULONG)Address; Ptr <= (ULONG)Address + Size; Ptr++)
	{
		MmRet = MiIsAddressValidEx((PVOID)Ptr);
		if (MmRet != VCS_VALID){
			return FALSE;
		}
	}
	return TRUE;
}


h文件

#include "ntifs.h"

typedef struct _MMPTE_SOFTWARE {
	ULONG Valid : 1;
	ULONG PageFileLow : 4;
	ULONG Protection : 5;
	ULONG Prototype : 1;
	ULONG Transition : 1;
	ULONG PageFileHigh : 20;
} MMPTE_SOFTWARE;

typedef struct _MMPTE_TRANSITION {
	ULONG Valid : 1;
	ULONG Write : 1;
	ULONG Owner : 1;
	ULONG WriteThrough : 1;
	ULONG CacheDisable : 1;
	ULONG Protection : 5;
	ULONG Prototype : 1;
	ULONG Transition : 1;
	ULONG PageFrameNumber : 20;
} MMPTE_TRANSITION;

typedef struct _MMPTE_PROTOTYPE {
	ULONG Valid : 1;
	ULONG ProtoAddressLow : 7;
	ULONG ReadOnly : 1;  // if set allow read only access.
	ULONG WhichPool : 1;
	ULONG Prototype : 1;
	ULONG ProtoAddressHigh : 21;
} MMPTE_PROTOTYPE;

typedef struct _MMPTE_HARDWARE {
	ULONG Valid : 1;
	ULONG Write : 1;       // UP version
	ULONG Owner : 1;
	ULONG WriteThrough : 1;
	ULONG CacheDisable : 1;
	ULONG Accessed : 1;
	ULONG Dirty : 1;
	ULONG LargePage : 1;
	ULONG Global : 1;
	ULONG CopyOnWrite : 1; // software field
	ULONG Prototype : 1;   // software field
	ULONG reserved : 1;    // software field
	ULONG PageFrameNumber : 20;
} MMPTE_HARDWARE, *PMMPTE_HARDWARE;

typedef struct _MMPTE {
	union  {
		ULONG Long;
		MMPTE_HARDWARE Hard;
		MMPTE_PROTOTYPE Proto;
		MMPTE_SOFTWARE Soft;
		MMPTE_TRANSITION Trans;
	} u;
} MMPTE, *PMMPTE;

typedef struct _MMPTE_SOFTWARE_PAE {
	ULONGLONG Valid : 1;
	ULONGLONG PageFileLow : 4;
	ULONGLONG Protection : 5;
	ULONGLONG Prototype : 1;
	ULONGLONG Transition : 1;
	ULONGLONG Unused : 20;
	ULONGLONG PageFileHigh : 32;
} MMPTE_SOFTWARE_PAE;

typedef struct _MMPTE_TRANSITION_PAE {
	ULONGLONG Valid : 1;
	ULONGLONG Write : 1;
	ULONGLONG Owner : 1;
	ULONGLONG WriteThrough : 1;
	ULONGLONG CacheDisable : 1;
	ULONGLONG Protection : 5;
	ULONGLONG Prototype : 1;
	ULONGLONG Transition : 1;
	ULONGLONG PageFrameNumber : 24;
	ULONGLONG Unused : 28;
} MMPTE_TRANSITION_PAE;

typedef struct _MMPTE_PROTOTYPE_PAE {
	ULONGLONG Valid : 1;
	ULONGLONG Unused0: 7;
	ULONGLONG ReadOnly : 1;  // if set allow read only access.  LWFIX: remove
	ULONGLONG Unused1: 1;
	ULONGLONG Prototype : 1;
	ULONGLONG Protection : 5;
	ULONGLONG Unused: 16;
	ULONGLONG ProtoAddress: 32;
} MMPTE_PROTOTYPE_PAE;

typedef struct _MMPTE_HARDWARE_PAE {
	ULONGLONG Valid : 1;
	ULONGLONG Write : 1;        // UP version
	ULONGLONG Owner : 1;
	ULONGLONG WriteThrough : 1;
	ULONGLONG CacheDisable : 1;
	ULONGLONG Accessed : 1;
	ULONGLONG Dirty : 1;
	ULONGLONG LargePage : 1;
	ULONGLONG Global : 1;
	ULONGLONG CopyOnWrite : 1; // software field
	ULONGLONG Prototype : 1;   // software field
	ULONGLONG reserved0 : 1;  // software field
	ULONGLONG PageFrameNumber : 24;
	ULONGLONG reserved1 : 28;  // software field
} MMPTE_HARDWARE_PAE, *PMMPTE_HARDWARE_PAE;

typedef struct _MMPTE_PAE {
	union  {
		LARGE_INTEGER Long;
		MMPTE_HARDWARE_PAE Hard;
		MMPTE_PROTOTYPE_PAE Proto;
		MMPTE_SOFTWARE_PAE Soft;
		MMPTE_TRANSITION_PAE Trans;
	} u;
} MMPTE_PAE;

typedef MMPTE_PAE *PMMPTE_PAE;

#define PTE_BASE    0xC0000000
#define PDE_BASE    0xC0300000
#define PDE_BASE_PAE 0xc0600000

#define MiGetPdeAddress(va)  ((MMPTE*)(((((ULONG)(va)) >> 22) << 2) + PDE_BASE))
#define MiGetPteAddress(va) ((MMPTE*)(((((ULONG)(va)) >> 12) << 2) + PTE_BASE))

#define MiGetPdeAddressPae(va)   ((PMMPTE_PAE)(PDE_BASE_PAE + ((((ULONG)(va)) >> 21) << 3)))
#define MiGetPteAddressPae(va)   ((PMMPTE_PAE)(PTE_BASE + ((((ULONG)(va)) >> 12) << 3)))

#define MM_ZERO_PTE 0
#define MM_ZERO_KERNEL_PTE 0


#define MM_ZERO_ACCESS         0  // this value is not used.
#define MM_READONLY            1
#define MM_EXECUTE             2
#define MM_EXECUTE_READ        3
#define MM_READWRITE           4  // bit 2 is set if this is writable.
#define MM_WRITECOPY           5
#define MM_EXECUTE_READWRITE   6
#define MM_EXECUTE_WRITECOPY   7
#define MM_NOCACHE             8

#define PAE_ON (1<<5)

typedef enum VALIDITY_CHECK_STATUS{
	VCS_INVALID,
	VCS_VALID,
	VCS_TRANSITION,
	VCS_PAGEDOUT,
	VCS_DEMANDZERO,
	VCS_PROTOTYPE
}VALIDITY_CHECK_STATUS;

PCHAR MiProtectionToString[] = {
	"MM_ZERO_ACCESS", //         0  // this value is not used.
	"MM_READONLY", //            1
	"MM_EXECUTE", //             2
	"MM_EXECUTE_READ", //        3
	"MM_READWRITE", //           4  // bit 2 is set if this is writable.
	"MM_WRITECOPY", //           5
	"MM_EXECUTE_READWRITE", //   6
	"MM_EXECUTE_WRITECOPY", //   7
	"MM_NOCACHE"            //   8
};
2016-8-13 03:24
0
雪    币: 13
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
能给个正确的写法吗,不太熟悉这块。
2016-8-15 09:27
0
雪    币: 522
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
代码逻辑上就是错的  跟熟不熟悉完全无关  
况且6楼已经贴出了完整的检测函数     还在问代码要怎么写?   还举白旗投降 ?
2016-8-15 09:49
0
雪    币: 0
活跃值: (143)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
我也是菜鸟一只,我也遇到过这样的问题,对于检测,我感觉6楼的代码很精细。
但是明明这块内存里面确实应该有值,但是取出来就是非法的,这个该怎么办?怎么才能访问到里面的值呢
2016-8-15 12:41
0
雪    币: 13
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10

感谢,很有参考价值。
2016-8-17 09:35
0
游客
登录 | 注册 方可回帖
返回
//