nt内核里的对象管理[2]: Object Table

一个进程在其生命周期内可能会打开很多个内核对象,这些对象需要得到很好的管理才能保证效率。NT内核使用Table来保存这些打开对象,该Table的指针存放在EPROCESS->ObjectTable里。gussing.cnblogs.com

当我们访问ObjectTable时,需要确定的有两个信息:Table地址和表的级数。Object Table并不总是一个巨大而平坦的线性列表,因为有时候内核对象的数量会非常之大,一个线性列表不够用。实际情况是,当对象数目大于512时EPROCESS->ObjectTable指向的是一个二级表;而当对象数目超过512*1024时,EPROCESS->ObjectTable指向的是一个三级表。Object Table的值一定是8的倍数,也就是说末三位一定是0,所以EPROCESS->ObjectTable字段的末三位可以用来记录额外信息也就是表的级数,0表示一级表,1代表二级表,2代表三级表。gussing.cnblogs.com

一级表的结构:

image

整个表的大小算下来正好4096B,为1 page。内存管理组件是以页为单位进行管理的,把一段信息的大小局限在一页内可以有效提高效率。

插播一条广告:为了学习nt内核,我写了一个山寨 ProcessExplorer,可以查看进程信息,线程信息,handle列表,已加载dll列表,已加载驱动列表等等信息,所有信息都是手工收集,用 过的API只有DeviceIoControl一个,当然,内核导出函数还是用了不少的。能把指定dll注入指定进程,还能强杀某些杀毒软件。注意!目前 只支持xp sp3,其他版本的windows未经测试。

该玩具源代码放在http://code.google.com/p/yasi/上,欢迎各位去取。另外,这是本人习作,高手不准笑。。。

 

二级表的结构:gussing.cnblogs.com

image

在二级表中,ObjectCode指向的不是对象表本身,而是1024个对象表的地址组成的指针数组。每个表项都是HandleTable*类型的指针,指向一个一级表。

这里还有一个陷阱:并不是指针数组里的每一项都是有效值。比如你之前打开了三个内核对象,然后关闭第二个,那么数组的第一项和第三项仍然有效,第二项却成了无效指针,这就是所谓的“空洞”,遍历ObjectTable时一定得注意跳过这些空洞,否则等待你的就是蓝屏死机。

三级表结构gussing.cnblogs.com

image

 

 

 

 

二级表和三级表中的高层表是一个指针数组,每项4字节,所以总共可以容纳4096/4=1024项。

Object Table的结构介绍完毕,其实相当简单。gussing.cnblogs.com

再来看HANDLE_TABLE_ENTRY里到底存了什么。HANDLE_TABLE_ENTRY结构定义如下:

typedef struct _HANDLE_TABLE_ENTRY
{
        union{
                PVOID Object;
                ULONG ObAttributes;
                PVOID InfoTable;
                ULONG Value;
        }u1; gussing.cnblogs.com
        union{
                struct _s1
                {
                        union{
                                ULONG GrantedAccess;
                                struct _s2{
                                        unsigned short GrantedAccessIndex;
                                        unsigned short GreatorBackTraceIndex;
                                }s2;
                        }u2;
                }s1;
                int NextFreeTableEntry;
        }u3;
}HANDLE_TABLE_ENTRY,*PHANDLE_TABLE_ENTRY;

这是一个8字节大小的内存区域,前四个字节是Object Header的地址,后四个字节为一些管理域。需要注意的是,HANDLE_TABLE_ENTRY->Object也是8字节对齐的,所以末三位清零才是真正的Object Header的地址。

最后让我们看看从HANDLE到Object的全过程:gussing.cnblogs.com

image

posted @ 2009-08-30 16:30  gussing  阅读(1439)  评论(0编辑  收藏  举报