系列文章目录
//搜索给定长度的空间地址区间
MmFindGap();
PMADDRESS_SPACE AddressSpace,//该进程用户空间
ULONG_PTR Length,//寻找的空间间隔大小
ULONG_PTR Granularity,//粒度位,表明空间起点的对齐要求,注意是起点地址
ULONG_PTR TopDown);
函数的定义:
PVOID
NTAPI
MmFindGap(
PMADDRESS_SPACE AddressSpace,
ULONG_PTR Length,
ULONG_PTR Granularity,
BOOLEAN TopDown
);
文章目录
MmFindGap函数的实现
//搜索给定长度的空间地址区间
//所属给定长度的空间地址区间
PVOID STDCALL
MmFindGap(
PMADDRESS_SPACE AddressSpace,
ULONG_PTR Length,
ULONG_PTR Granularity,
BOOLEAN TopDown)
{
if (TopDown)//表示寻找的方向时从高端到低段还是从低端往高端
return MmFindGapTopDown(AddressSpace, Length, Granularity);//高端往地段
return MmFindGapBottomUp(AddressSpace, Length, Granularity);//低端往高端
}
//搜索给定长度的空间地址区间
PMADDRESS_SPACE AddressSpace,//该进程用户空间
ULONG_PTR Length,//寻找的空间间隔大小
ULONG_PTR Granularity,//粒度位,表明空间起点的对齐要求,注意是起点地址
ULONG_PTR TopDown);
参数TopDown表示孕照的方向是从高往低端搜索还是低端往高端搜索。我们开看其中之一,即MmFindGapBottomUp().参数Granularity表明对于区间起点地址的颗粒度要求,即边界对齐的要求,大哥比方,假设颗粒度位16字节,长度要求为8,那么空间【0x3,0x14】是不符合要求的。这个区间的绝对长度大于8,但是我如把区间的起始与0x10对齐,剩下的长度就不够了。 而空间【0x10,0x18】绝对长度虽然小于前者,去能满足要求。
static PVOID
MmFindGapBottomUp(
PMADDRESS_SPACE AddressSpace,
ULONG_PTR Length,
ULONG_PTR Granularity)
{
PVOID HighestAddress = AddressSpace->LowestAddress < MmSystemRangeStart ?
(PVOID)((ULONG_PTR)MmSystemRangeStart - 1) : (PVOID)MAXULONG_PTR;
PVOID AlignedAddress;
PMEMORY_AREA Node;
PMEMORY_AREA FirstNode;
PMEMORY_AREA PreviousNode;
MmVerifyMemoryAreas(AddressSpace);
DPRINT("LowestAddress: %p HighestAddress: %p\n",
AddressSpace->LowestAddress, HighestAddress);
AlignedAddress = MM_ROUND_UP(AddressSpace->LowestAddress, Granularity);
/* Special case for empty tree. */
if (AddressSpace->MemoryAreaRoot == NULL)
{
if ((ULONG_PTR)HighestAddress - (ULONG_PTR)AlignedAddress >= Length)
{
DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress);
return AlignedAddress;
}
DPRINT("MmFindGapBottomUp: 0\n");
return 0;
}
/* Go to the node with lowest address in the tree. */
FirstNode = Node = MmIterateFirstNode(AddressSpace->MemoryAreaRoot);
/* Traverse the tree from left to right. */
PreviousNode = Node;
for (;;)
{
Node = MmIterateNextNode(Node);
if (Node == NULL)
break;
AlignedAddress = MM_ROUND_UP(PreviousNode->EndingAddress, Granularity);
if (Node->StartingAddress > AlignedAddress &&
(ULONG_PTR)Node->StartingAddress - (ULONG_PTR)AlignedAddress >= Length)
{
DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress);
return AlignedAddress;
}
PreviousNode = Node;
}
/* Check if there is enough space after the last memory area. */
AlignedAddress = MM_ROUND_UP(PreviousNode->EndingAddress, Granularity);
if ((ULONG_PTR)HighestAddress > (ULONG_PTR)AlignedAddress &&
(ULONG_PTR)HighestAddress - (ULONG_PTR)AlignedAddress >= Length)
{
DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress);
return AlignedAddress;
}
/* Check if there is enough space before the first memory area. */
AlignedAddress = MM_ROUND_UP(AddressSpace->LowestAddress, Granularity);
if (FirstNode->StartingAddress > AlignedAddress &&
(ULONG_PTR)FirstNode->StartingAddress - (ULONG_PTR)AlignedAddress >= Length)
{
DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress);
return AlignedAddress;
}
DPRINT("MmFindGapBottomUp: 0\n");
return 0;
}