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

阅读提示:由于继续使用了chichou同学的CodeHighlighter来修饰代码,造成文章字数过多,故分成三篇,且后两篇内容的顺序稍有调整,阅读时请根据大标题的顺序来~

前置知识:Windows句柄表的基本结构
本文以WRK1.2的代码为参考,主要分析Windows句柄表的分配算法,其实只要了解了句柄表的结构,就很容易理解在分配句柄表过程中的每一步操作是何含义,理解之后你会感觉,这个其实算不上什么算法,只能叫做一个规则吧

一、首先来看ExCreateHandleTable(),该函数创建一个HANDLE_TABLE结构;
其过程是调用ExpAllocateHandleTable()完成申请HANDLE_TABLE的工作,然后把申请到的HANDLE_TABLE放到句柄表双链中去
所有进程的HANDLE_TABLE就这样连接在一起(如果有人用过ZwQuerySystemInformation枚举系统中的所有句柄时,就是沿着这条双向链表走的),而PspCidTable也由该函数创建,但这后又被从该双链中移除,成为一个独立的句柄表(谁让它特殊~)
//核心是下面两句

HandleTable = ExpAllocateHandleTable( Process, TRUE );//创建句柄表
InsertTailList( &HandleTableListHead, &HandleTable->HandleTableList );//放入双向链表中
=======================================================
PHANDLE_TABLE
ExpAllocateHandleTable (
IN PEPROCESS Process OPTIONAL,
IN BOOLEAN DoInit
);

过程分析:

1.申请一块PagedPool作为HANDLE_TABLE,大小为sizeof(HANDLE_TABLE)
2.为HANDLE_TABLE申请一块PagePool内存作为第一个一级表,大小为PAGE_SIZE,以后的一级表由ExpAllocateLowLevelTable来申请

//设置TableCode为刚申请的一级表,这里其实隐含了句柄表为一级这个事实
HandleTable->TableCode = (ULONG_PTR)HandleTableTable;
//下面是对这个刚申请的一级表进行初始化
HandleEntry = &HandleTableTable[]; //第一个HANDLE_TABLE_ENTRY
HandleEntry->NextFreeTableEntry = EX_ADDITIONAL_INFO_SIGNATURE;//-2,作为标志;
HandleEntry->Value = ; //对象值为0,对应于无效句柄NULL
//
// For duplicate calls we skip building the free list as we rebuild it manually as
// we traverse the old table we are duplicating
//
if (DoInit) { //这个参数在普通调用时为TRUE,仅在复制句柄表时则为False,因为复制时并不需要重新分配句柄
HandleEntry++; //从第二个HANDLE_TABLE_ENTRY开始
//
// Now setup the free list. We do this by chaining together the free
// entries such that each free entry give the next free index (i.e.,
// like a fat chain). The chain is terminated with a 0. Note that
// we'll skip handle zero because our callers will get that value
// confused with null.
//
for (i = ; i < LOWLEVEL_COUNT - ; i += ) {
HandleEntry->Value = ; //对象值初始化为0
//FreeHandle即自由的,未被使用的句柄
HandleEntry->NextFreeTableEntry = (i+)*HANDLE_VALUE_INC; //构建FreeHandle列表,在初始化时,每一个HANDLE_TABLE_ENTRY都指向下一个句柄.这里的NextFreeTableEntry的值准确说是下一个FreeHandle,这样构成了一个单向链表一样的结构
HandleEntry++;
}
//对最后一项作特殊处理
HandleEntry->Value = ;
HandleEntry->NextFreeTableEntry = ; //最后一项的NextFreeTableEntry为0
HandleTable->FirstFree = HANDLE_VALUE_INC; //把刚初始化完的句柄表的FirstFree设为4,即第一个可用句柄
} HandleTable->NextHandleNeedingPool = LOWLEVEL_COUNT * HANDLE_VALUE_INC; //一级表最大句柄
//
// Setup the necessary process information
//
HandleTable->QuotaProcess = Process; //设置所属的Process
HandleTable->UniqueProcessId = PsGetCurrentProcess()->UniqueProcessId; //调置所属Process的ProcessId
HandleTable->Flags = ;

=============================================================================================================

二、申请低级表,即最底层一级的表.每个HANDLE_TABLE的第一个一级表在创建HANDLE_TABLE时就被创建了,ExpAllocateLowLevelTable用于提供在其它时候创建一级表的支持,比如句柄表已经为二级时再申请句柄表时只需要申请创建一个一级表并加入二级表中即可.

PHANDLE_TABLE_ENTRY
ExpAllocateLowLevelTable (
IN PHANDLE_TABLE HandleTable,
IN BOOLEAN DoInit
)
/*++
Routine Description:
This worker routine allocates a new low level table Note: The caller must have already locked the handle table
Arguments:
HandleTable - Supplies the handle table being used
DoInit - If FALSE the caller (duplicate) doesn't need the free list maintained
Return Value:
Returns - a pointer to a low-level table if allocation is
successful otherwise the return value is null.
--*/
{
ULONG k;
PHANDLE_TABLE_ENTRY NewLowLevel = NULL, HandleEntry;
ULONG BaseHandle; //
// Allocate the pool for lower level
//
NewLowLevel = ExpAllocateTablePagedPoolNoZero( HandleTable->QuotaProcess,
TABLE_PAGE_SIZE
);//申请内存,大小为一级表的大小TABLE_PAGE_SIZE
if (NewLowLevel == NULL) {
return NULL;
}
//
// We stamp with EX_ADDITIONAL_INFO_SIGNATURE to recognize in the future this
// is a special information entry
//
//下面三行代码为初始化,这个同刚创建HANDLE_TABLE时创建第一个一级表时的工作基本相同,不多说
HandleEntry = &NewLowLevel[];
HandleEntry->NextFreeTableEntry = EX_ADDITIONAL_INFO_SIGNATURE;
HandleEntry->Value = ;
//
// Initialize the free list within this page if the caller wants this
//
if (DoInit) {
HandleEntry++;
//
// Now add the new entries to the free list. To do this we
// chain the new free entries together. We are guaranteed to
// have at least one new buffer. The second buffer we need
// to check for.
//
// We reserve the first entry in the table to the structure with
// additional info
//
//
// Do the guaranteed first buffer
//
//这里是构建FreeHandleList,也是将每一个HANDLE_TABLE_ENTRY的NextFreeTableEntry指向下一个可用句柄.
//但是由于这里不是第一个一级表,所以句柄值的计算稍有不同,需要考虑加上前面的部分
BaseHandle = HandleTable->NextHandleNeedingPool + * HANDLE_VALUE_INC;
//BaseHandle是当前新分配的句柄表中的最小句柄+4,即未申请本表时的最大Handle(句柄表的最大Handle即HandleTable->NextHandleNeedingPool)再加上8,也就是说跳过了第一个用作无效标记的HANDLE_TABLE_ENTRY(占一个句柄索引),
//以第二个作为新句柄表起始点的HANDLE_TABLE_ENTRY为起始点(因为第二个HANDLE_TABLE_ENTRY才是有效的,因此从这里开始构建FreeHandleList的话,它的下一个FreeHandle应该指向第三个HANDLE_TABLE_ENTRY,
//而第三个HANDLE_TABLE_ENTRY的句柄在当前句柄表内的偏移为2*HANDLE_VALUE_INC=8)
for (k = BaseHandle; k < BaseHandle + (LOWLEVEL_COUNT - ) * HANDLE_VALUE_INC; k += HANDLE_VALUE_INC) { //k的值为BaseHandle开始,以HANDLE_VALUE_INC递增,增量为4
HandleEntry->NextFreeTableEntry = k; //这里构建了FreeHandleList,可以实验观察之
HandleEntry->Value = ;
HandleEntry++;
}
HandleEntry->NextFreeTableEntry = ; //最后一个置0,作为结束标记
HandleEntry->Value = ;
}
return NewLowLevel;
}

未完待续~

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

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

    原文发表于百度空间,2009-03-31========================================================================== 理论结合实 ...

  2. 【旧文章搬运】Windows句柄表分配算法分析(三)

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

  3. 【旧文章搬运】Windows句柄表分配算法分析(二)

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

  4. 【旧文章搬运】Windows句柄分配算法(一)

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

  5. 【旧文章搬运】Windows句柄分配算法(二)

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

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

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

  7. 【旧文章搬运】Windows内核常见数据结构(进程相关)

    原文发表于百度空间,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. Jquery表单序列化和json操作

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. Go语言并发之美

    简介           多核处理器越来越普及,那有没有一种简单的办法,能够让我们写的软件释放多核的威力?答案是:Yes.随着Golang, Erlang, Scale等为并发设计的程序语言的兴起,新 ...

  3. ImportError: No module named _curses;Color support is disabled, python-curses is not installed.解决办法

    linux系统默认安装了python2.6, 但是发现python2.7 import curses时 提示 找不到_curses 错误.  用pip(python2.7 )安装了curses-204 ...

  4. JavaScript - 正则表达式解惑

    正则表达式手册: http://tool.oschina.net/uploads/apidocs/jquery/regexp.html 正则表达式测试地址: http://tool.chinaz.co ...

  5. underscore.js 页面数据渲染

    1.underscore.js  源码 // Underscore.js 1.8.3 // http://underscorejs.org // (c) 2009-2015 Jeremy Ashken ...

  6. Linux/UNIX之文件和文件夹(2)

    文件和文件夹(2) link.ulink.remove和rename函数 #include <unistd.h> int link(const char *oldpath, const c ...

  7. Java学习之基本概念

    1.java体系结构: j2se:是Java的标准版,用于标准的应用开. j2ee:是Java的企业版,用于企业级的应用服务,web服务开发. j2me:是Java的微型版,用户手机或嵌入式开发. p ...

  8. centos下的hadoop集群实现ssh的无密码登陆

    CentOS 下SSH无密码登录的配置 最近学习Hadoop.它要求各节点之间通过SSH无密码登录,配置SSH的时候费了一番功夫,记录下来,以备忘. 配置SSH无密码登录需要3步: 1.生成公钥和私钥 ...

  9. UVA 11246 - K-Multiple Free set(数论推理)

    UVA 11246 - K-Multiple Free set 题目链接 题意:一个{1..n}的集合.求一个子集合.使得元素个数最多,而且不存在有两个元素x1 * k = x2,求出最多的元素个数是 ...

  10. VUE清除组件内部定时器

    定时器如果不手动清除,只会在离开当前页面或者F5刷新后才会清除.由于vue项目是SPA应用,离开当前组件后并不会清除定时器,所以需要我们手动去清除定时器.但当我们将清除定时器clearInterval ...