一直在想windows下的句柄是怎么进行分配和管理的
而这个句柄分配的算法又是windows不与公布的
在网上找了下 发现这方面的资料很少啊 于是自己对着WRK和reactOS看了一下午
虽然明白了一点点 但是还是有好多地方很迷糊 希望大牛们指导一下
从ExCreateHandle开始
到ExpAllocateHandleEntry
再到ExpAllocateHandleTableEntrySlow
定位句柄分配算法大概就位于此处
if ( TableLevel == 0 ) {
NewMidLevel = ExpAllocateMidLevelTable( HandleTable, DoInit, &NewLowLevel );
if (NewMidLevel == NULL) {
return FALSE;
}
NewMidLevel[1] = NewMidLevel[0];
NewMidLevel[0] = (PHANDLE_TABLE_ENTRY)CapturedTable;
CapturedTable = ((ULONG_PTR)NewMidLevel) | 1;
OldValue = InterlockedExchangePointer( (PVOID *)&HandleTable->TableCode, (PVOID)CapturedTable );
} else if (TableLevel == 1) {
PHANDLE_TABLE_ENTRY *TableLevel2 = (PHANDLE_TABLE_ENTRY *)CapturedTable;
i = HandleTable->NextHandleNeedingPool / (LOWLEVEL_COUNT * HANDLE_VALUE_INC);
if (i < MIDLEVEL_COUNT) {
NewLowLevel = ExpAllocateLowLevelTable( HandleTable, DoInit );
if (NewLowLevel == NULL) {
return FALSE;
}
OldValue = InterlockedExchangePointer( (PVOID *) (&TableLevel2[i]), NewLowLevel );
EXASSERT (OldValue == NULL);
} else {
NewHighLevel = ExpAllocateTablePagedPool( HandleTable->QuotaProcess,
HIGHLEVEL_SIZE
);
if (NewHighLevel == NULL) {
return FALSE;
}
NewMidLevel = ExpAllocateMidLevelTable( HandleTable, DoInit, &NewLowLevel );
if (NewMidLevel == NULL) {
ExpFreeTablePagedPool( HandleTable->QuotaProcess,
NewHighLevel,
HIGHLEVEL_SIZE
);
return FALSE;
}
NewHighLevel[0] = (PHANDLE_TABLE_ENTRY*)CapturedTable;
NewHighLevel[1] = NewMidLevel;
CapturedTable = ((ULONG_PTR)NewHighLevel) | 2;
OldValue = InterlockedExchangePointer( (PVOID *)&HandleTable->TableCode, (PVOID)CapturedTable );
}
} else if (TableLevel == 2) {
ULONG RemainingIndex;
PHANDLE_TABLE_ENTRY **TableLevel3 = (PHANDLE_TABLE_ENTRY **)CapturedTable;
i = HandleTable->NextHandleNeedingPool / (MIDLEVEL_THRESHOLD * HANDLE_VALUE_INC);
if (i >= HIGHLEVEL_COUNT) {
return FALSE;
}
if (TableLevel3[i] == NULL) {
NewMidLevel = ExpAllocateMidLevelTable( HandleTable, DoInit, &NewLowLevel );
if (NewMidLevel == NULL) {
return FALSE;
}
OldValue = InterlockedExchangePointer( (PVOID *) &(TableLevel3[i]), NewMidLevel );
EXASSERT (OldValue == NULL);
} else {
RemainingIndex = (HandleTable->NextHandleNeedingPool / HANDLE_VALUE_INC) -
i * MIDLEVEL_THRESHOLD;
j = RemainingIndex / LOWLEVEL_COUNT;
NewLowLevel = ExpAllocateLowLevelTable( HandleTable, DoInit );
if (NewLowLevel == NULL) {
return FALSE;
}
OldValue = InterlockedExchangePointer( (PVOID *)(&TableLevel3[i][j]) , NewLowLevel );
EXASSERT (OldValue == NULL);
}
}
大致流程简化如下
if ( TableLevel == 0 )
{
NewMidLevel = ExpAllocateMidLevelTable( HandleTable, DoInit, &NewLowLevel );
}
else if ( TableLevel == 1 )
{
if (i < MIDLEVEL_COUNT)
{
NewLowLevel = ExpAllocateLowLevelTable( HandleTable, DoInit );
}
else
{
NewHighLevel = ExpAllocateTablePagedPool( HandleTable->QuotaProcess,
HIGHLEVEL_SIZE
);
NewMidLevel = ExpAllocateMidLevelTable( HandleTable, DoInit, &NewLowLevel );
}
}
else if (TableLevel == 2)
{
if (i >= HIGHLEVEL_COUNT)
return FALSE;
if (TableLevel3[i] == NULL)
NewMidLevel = ExpAllocateMidLevelTable( HandleTable, DoInit, &NewLowLevel );
else
NewLowLevel = ExpAllocateLowLevelTable( HandleTable, DoInit );
}
思路可能是这样的 如果这一级句柄表满了以后就分配更高一级的句柄表,并修改HANDLE_TABLE结构中相应的部分使其指向高一级的句柄表 在高一级的句柄表中指向满掉的那个句柄表
这里有一个问题 当level=0时 并没有做任何判断 就用ExpAllocateMidLevelTable分配了一个中级表 这是为什么呢? 不是应该判断一下0级表有没有满吗?就像下面的都判断了i的值,这里为什么没有判断?
ps: 不知道有没有句柄算法的更详细的一点资料?
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法