【旧文章搬运】Windows句柄表分配算法分析(实验部分)

时间:2022-09-25 09:06:07

原文发表于百度空间,2009-03-31
==========================================================================

理论结合实践,这是我一贯的学习方法~~
实验目的:以实验的方式观察PspCidTable的变化,从中了解Windows句柄表的分配过程.
实验器材:Windbg,RunIt(一个可控的不断创建线程的程序),DebugView
知识回顾:

【旧文章搬运】Windows句柄表分配算法分析(实验部分)

如图所示,句柄表的结构根据TableLevel来确定:
TableLevel为0时,CapturedTable是一级表(蓝箭头)
TableLevel为1时,CapturedTable是二级表,CapturedTable[i]是一级表(绿箭头)
TableLevel为2时,CapturedTable是三级表,CapturedTable[i]是二级表,CapturedTable[i][j]是一级表(红箭头)
三级表的内容是二级表指针,二级表的内容是一级表指针,一级表中放的才是对象及访问属性(HANDLE_TABLE_ETNRY结构)

准备工作:获取PspCidTable的基本信息

lkd> dd PspCidTable l1
8055a360 e1001810 //获取PspCidTable的地址
lkd> dt _HANDLE_TABLE e1001810
nt!_HANDLE_TABLE
+0x000 TableCode : 0xe1003000 //表基址为0xe1003000,一级表
+0x004 QuotaProcess : (null)
+0x008 UniqueProcessId : (null)
+0x00c HandleTableLock : [] _EX_PUSH_LOCK
+0x01c HandleTableList : _LIST_ENTRY [ 0xe100182c - 0xe100182c ]
+0x024 HandleContentionEvent : _EX_PUSH_LOCK
+0x028 DebugInfo : (null)
+0x02c ExtraInfoPages :
+0x030 FirstFree : 0x308
+0x034 LastFree : 0x34c
+0x038 NextHandleNeedingPool : 0x800 //当前的句柄上限
+0x03c HandleCount :
+0x040 Flags :
+0x040 StrictFIFO : 0y1

此时可以观察到PspCidTable=e1001810,当前TableCode为0xe1003000,低两位表明是一级表,表地址为0xe1003000

lkd> dd 0xe1003000
e1003000 fffffffe 821bb661
e1003010 821bb3e9 821ba021
e1003020 821bad21 821baaa9
e1003030 821ba831 821ba5b9
e1003040 821ba341 821b9021
e1003050 821b9da9 821b9b31
e1003060 821b98b9 821b9641
e1003070 821b93c9 821b8021

这时可以看到一级表存放的进线程对象了

实验一:观察句柄表的升级
由于二级表升级为三级表需要极大的句柄容量,因此我们通常只能观察到句柄表由一级表升为二级表的过程
运行RunIt.exe,按回车不断创建线程,直至新线程的ThreadId大于当前句柄表的上限0x800.

此时再观察PspCidTable:

lkd> dt _HANDLE_TABLE e1001810
nt!_HANDLE_TABLE
+0x000 TableCode : 0xe11a4001 //这时已经为二级表了
+0x004 QuotaProcess : (null)
+0x008 UniqueProcessId : (null)
+0x00c HandleTableLock : [] _EX_PUSH_LOCK
+0x01c HandleTableList : _LIST_ENTRY [ 0xe100182c - 0xe100182c ]
+0x024 HandleContentionEvent : _EX_PUSH_LOCK
+0x028 DebugInfo : (null)
+0x02c ExtraInfoPages :
+0x030 FirstFree : 0x860
+0x034 LastFree : 0x38c
+0x038 NextHandleNeedingPool : 0x1000 //句柄上限达到了0x800*2=0x1000
+0x03c HandleCount :
+0x040 Flags :
+0x040 StrictFIFO : 0y1

这时的TableCode低两位表时现在是二级表,掩去低两位就是二级表的地址0xe11a4000了

lkd> dd 0xe11a4000 //观察二级表的内容
e11a4000 e1003000 e11b5000
e11a4010
e11a4020
e11a4030
e11a4040
e11a4050
e11a4060
e11a4070

可以看到,原来的一级表e1003000已经成为了二级表中的第一个元素.同时新分配了一个一级表为e11b5000.这样,句柄表的升级就完成了

实验二:观察新分配的句柄表是如何填充的
前面已经分析过,新分配的句柄表被填充成一个有序的FreeHandle序列.
观察新分配的这个二级表:

lkd> dd e11b5000
e11b5000 fffffffe 81f008b9
e11b5010 81f00641 81f003c9
e11b5020 81f5d021 81f5dda9
e11b5030 81f5db31 81f5d8b9
e11b5040 81f5d641 81f5d3c9
e11b5050 81eff021 81effda9
e11b5060 81effb31 81eff8b9
e11b5070 81eff641 81eff3c9 //RunIt创建的最后一个线程的ETHREAD在e11b5078处
lkd> dd
e11b5080 //这里的一部分句柄也被使用过了,因为可能别的进程也创建了线程
e11b5090
e11b50a0 0000038c 81f5cda9
e11b50b0 0000084c
e11b50c0
e11b50d0 0000086c
e11b50e0
e11b50f0 0000087c
lkd>
e11b5100
e11b5110 0000088c
e11b5120
e11b5130 0000089c 000008a0
e11b5140 000008a4 000008a8
e11b5150 000008ac 000008b0
e11b5160 000008b4 000008b8
e11b5170 000008bc 000008c0

由图可知,最后一个ThreadId=0x83c,那么它在第二个表中的偏移是e11b5000+(0x83c-0x800)*2=e11b5078

从e11b5080到e11b50c0这部分的内容表明该范围内的部分句柄已经被使用过且又释放了(如果想避免该问题,你可以使用livekd的方式进行本实验,这样中断到调试器时就不会有其它动作来干扰我们的观察),但是尚未影响到e11b50c0之后的部分.
来观察这里:

e11b50c0
e11b50d0 0000086c
e11b50e0
e11b50f0 0000087c

e11b50c0作为二级表中的第二个一级表,它所对应的句柄为:

(e11b50c0-e11b5000)/2+0x800*(2-1)=0x860 //如果了解了句柄表的基本结构,这个计算很容易理解
而它的NextFreeHadleTableEntry则指向它紧挨着的下一个HANDLE_TABLE_ENTRY的所对应的句柄0x864
而且很容易看出0x864,0x868,0x86c...构成了一个等差数列.
这个结果可以与前面对ExpAllocateLowLevelTable函数的分析对比,两者是完全一致的.
附Runit程序的源码:

// RunIt.cpp : Defines the entry point for the console application.
//
#include <windows.h>
#include <stdio.h> DWORD WINAPI ThreadProc(LPVOID lpParameter );
HANDLE hEvent = NULL;
int main(int argc, char* argv[])
{ int i=;
DWORD tid=,oldtid=;
printf("MyPID=%d 0x%x\n",GetCurrentProcessId(),GetCurrentProcessId());
printf("每按一次回车键将产生一个新线程.\n");
hEvent=CreateEvent(NULL,FALSE,TRUE,"TEST");
for (i=;i<;i++)
{
getchar();
CreateThread(NULL,,ThreadProc,NULL,NULL,&tid);
printf("Runing %d...\tTID=%4d\t0x%x",i,tid,tid);
if (tid==oldtid)//已经达到当前进程所能创建线程数量的上限
{
break;
}
oldtid=tid;
//Sleep(20); }
while ()
{
Sleep();//停在这里
}
return ;
}
DWORD WINAPI ThreadProc(LPVOID lpParameter )
{
WaitForSingleObject(hEvent,INFINITE);
return ;
}

【旧文章搬运】Windows句柄表分配算法分析(实验部分)的更多相关文章

  1. 【旧文章搬运】Windows句柄表分配算法分析&lpar;一&rpar;

    原文发表于百度空间,2009-03-30========================================================================== 阅读提示: ...

  2. 【旧文章搬运】Windows句柄表分配算法分析&lpar;三&rpar;

    原文发表于百度空间,2009-03-30========================================================================== 三.当需要 ...

  3. 【旧文章搬运】Windows句柄表分配算法分析&lpar;二&rpar;

    原文发表于百度空间,2009-03-30========================================================================== 四.句柄表 ...

  4. 【旧文章搬运】Windows句柄分配算法&lpar;一&rpar;

    原文发表于百度空间,2009-04-04========================================================================== 分析了Wi ...

  5. 【旧文章搬运】Windows句柄分配算法&lpar;二&rpar;

    原文发表于百度空间,2009-04-04========================================================================== 在创建句柄 ...

  6. 【旧文章搬运】Windows句柄表格式

    原文发表于百度空间,2009-02-28========================================================================== 句柄是Wi ...

  7. 【旧文章搬运】Windows内核常见数据结构&lpar;进程相关&rpar;

    原文发表于百度空间,2008-7-24========================================================================== 进程的相关结 ...

  8. 【旧文章搬运】更正一个枚举PspCidTable时的错误

    原文发表于百度空间及看雪论坛,2009-02-27 看雪论坛地址:https://bbs.pediy.com/thread-82919.htm============================= ...

  9. 【旧文章搬运】深入分析Win7的对象引用跟踪机制

    原文发表于百度空间及看雪论坛,2010-09-12 看雪论坛地址:https://bbs.pediy.com/thread-120296.htm============================ ...

随机推荐

  1. SQL SERVER 2005 DBCC PAGE命令说明

    夏日福利: 小泽玛利亚的“专业摄影”性感写真集:http://947kan.com/video/player-52475-0-0.html ------------------------------ ...

  2. Android MediaPlayer的生命周期

    MediaPlayer的状态转换图也表征了它的生命周期,如下: 这张状态转换图清晰的描述了MediaPlayer的各个状态,也列举了主要的方法的调用时序,每种方法只能在一些特定的状态下使用,如果使用时 ...

  3. &lbrack;书目20160526&rsqb;Brain Rules 让大脑*:释放天赋的12条定律

    推荐序1 12条定律,让大脑更聪明推荐序2 走过迷雾地带前  言 人人都有一个不可思议的大脑 定律1:越运动,大脑越聪明 信不信,“驴友”比“沙发土豆”更聪明! 老板,请把办公室的咖啡机换成跑步机! ...

  4. 斯坦福大学CS224d基础1:线性代数回顾

    转自 http://blog.csdn.net/han_xiaoyang/article/details/51629242 斯坦福大学CS224d基础1:线性代数知识 作者:Zico Kolter ( ...

  5. intellij idea 如何更改编辑器文本字体和大小

    换上了intellij idea之后,第一件事就是想要改变下文字字体,因为在我这个27寸的2k分辨率的屏幕上,文字显然太小了. intellij idea字体设值分成两部分,一部分是UI部分字体字号设 ...

  6. Android progressBar 自定义圆形旋转图片

    项目需要中需要更换progressbar的旋转背景,在网上找了几种办法,但是都有各自的问题 于是结合网上所讲,研究了一下终于ok了: 一 首相在drawable文件夹中建立如下旋转动画文件 <? ...

  7. Delaunay三角剖分

    Bowyer-Watson算法:1.假设已经生成了连接若干个顶点的Delaunay三角网格:2.加入一个新的节点,找出所有外接圆包含新加入节点的三角形,并将这些三角形删除形成一个空洞:3.空洞的节点与 ...

  8. 【暑假】&lbrack;深入动态规划&rsqb;UVa 10618 Tango Tango Insurrection

    UVa 10618 Tango Tango Insurrection 题目: Problem A: Tango Tango Insurrection You are attempting to lea ...

  9. 使用Func&lt&semi;T1&comma; T2&comma; TResult&gt&semi;

    使用Func<T1, T2, TResult> 委托返回匿名对象   Func<T1, T2, TResult> 委托 封装一个具有两个参数并返回 TResult 参数指定的类 ...

  10. Customer Form Issue&colon; Automatic Matching Rule Set Defaults Value AutoRuleSet-1

    In this Document   Symptoms   Changes   Cause   Solution   References APPLIES TO: Oracle Receivables ...