天天看点

windows内核句柄表学习

Windows定义了很多内核对象:进程对象、线程对象、互斥量对象、信号量对象、事件对象、文件对象等等。在调用相应的函数创建这些对象后,我们都可以通过HANDLE类型的句柄来引用它们。

句柄必须通过句柄表才能找到所引用的内核对象。

Microsoft并未就句柄表发布过任何官方的文档。

通过windows公布的WRK(windows research kernel)源代码,可以了解windows句柄表。虽然是基于WRK的,不能保证其他版本的windows系统也采用相同的机制,但是或许都是大同小异的。

windows使用句柄对进程中的各种对象进行引用。实际上windows句柄就是一个索引,它存储了关联对象在句柄表的索引值,每个索引对应句柄表中的一个表项。通过句柄存储的索引,就可以很容易获得该句柄项对应的对象的指针。

句柄表中存储了很多了句柄表项;

句柄表是针对于进程而言的,在一个进程使用的句柄,直接在另一个进程中使用是毫无意义的。

在windows Server 2003(与WRK有相同的内核)中,句柄表是一个多层次的结构。

它的类型为:HANDLE_TABLE。定义如下:

    typedef struct _HANDLE_TABLE {

        ULONG_PTR TableCode;//指针指向句柄表的存储结构。

        struct _EPROCESS *QuotaProcess;  // 所属进程的指针

        HANDLE UniqueProcessId;     // 这个进程的 ProcessID

        EX_PUSH_LOCK  HandleTableLock[HANDLE_TABLE_LOCKS];//句柄表所,仅在句柄表扩展时使用。

        LIST_ENTRY HandleTableList;   // 所有的 HandleTAble 在内核中形成一个 List ,这是 Entry

        EX_PUSH_LOCK hangleConventionEvent//若在访问句柄表时发生了竞争则在此锁上等待。

        PHANDLE_TRACE_DEBUG_INFO DebugInfo;

        LONG extrainfoPag;

        ULONG FirstFree; // 空闲链表表头句柄索引。

        ULONG LastFree; // 最近被释放的句柄索引。

        ULONG NextHandleNeedingPool;//下一次句柄表扩展的起始句柄索引。

        LONG HandleCount;//正在使用的句柄表项数量。

    union{

          ULONG Flags;//标志域

          BOOLEAN StrictFIFO:1;//是否使用FIFO风格的重用。

         };

    } HANDLE_TABLE, *PHANDLE_TABLE;

句柄表项,它是HANDLE_TABLE_ENTRY结构,定义如下:

    typedef struct _HANDLE_TABLE_ENTRY

    {

        union {

                 PVOID Object;//内核对象指针。

                  ULONG ObAttributes;//内核对象属性。

                  PHANDLE_TABLE_ENTRY_INFO InfoTable;//

                  ULONG_PTR Value;

             };

        union {

                union {

                           ACCESS_MASK GrantedAccess;

                           struct{

                                     USHORT GrantedAccessIndex;

                              USHORT CreatorBackTraceIndex;

                             };

                          };

                LONG NextFreeTableEntry;

              };

    } HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;

window提供的API:GetCurrentThread和GetCurrentProcess,可以返回当前线程和进程的句柄。其实在句柄表中是没有存储当前进程的句柄和当前线程句柄。GetCurrentThread返回句柄的值是-2,当我们以此句柄作为参数传递给windows其他API函数时,在函数内部如果检测到该句柄值为-2,不会查找句柄表,立即返回到线程对象地址。类似的调用GetCurrentProcess时,其实返回的是-1,当使用此进程句柄时,同样不需要查找句柄表,会立即返回指向当前进程对象的指针。