⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jiurl玩玩win2k进程线程篇 handle_table.htm

📁 关于win2000核心编程的文章
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0074)http://jiurl.cosoft.org.cn/jiurl/document/JiurlPlayWin2k/PsHandleTable.htm -->
<HTML><HEAD><TITLE>JIURL玩玩Win2k进程线程篇 HANDLE_TABLE</TITLE>
<META content="text/html; charset=gb2312" http-equiv=Content-Type>
<STYLE type=text/css>.title {
	FONT-FAMILY: "黑体", Arial, sans-serif; FONT-SIZE: 21px; FONT-WEIGHT: bold; LINE-HEIGHT: 48px; TEXT-DECORATION: none
}
.author {
	FONT-FAMILY: "宋体"; FONT-SIZE: 12px; LINE-HEIGHT: 16px
}
.content {
	FONT-SIZE: 14px; LINE-HEIGHT: 20px
}
</STYLE>

<META content="MSHTML 5.00.2614.3500" name=GENERATOR></HEAD>
<BODY bgColor=#f7f7f7 topMargin=5>
<DIV align=center>
<CENTER>
<TABLE border=0 cellPadding=0 cellSpacing=0 height=29 width="96%">
  <TBODY>
  <TR>
    <TD class=title height=41 width="100%">
      <P align=center><FONT face=宋体>JIURL玩玩Win2k进程线程篇 </FONT><FONT 
      face=宋体>HANDLE_TABLE</FONT></P></TD></TR></CENTER>
  <TR>
    <TD class=author height=9 width="100%">
      <P align=center><FONT face=宋体>作者: <A 
      href="mailto:jiurl@mail.china.com">JIURL</A> </FONT></P></TD></TR>
  <TR>
    <TD class=author height=6 width="100%">
      <P align=center><FONT 
      face=宋体>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
      主页: <A href="http://jiurl.yeah.net/">http://jiurl.yeah.net/</A> 
    </FONT></P></TD></TR>
  <TR>
    <TD class=author height=2 width="100%">
      <P align=center><FONT face=宋体>&nbsp;&nbsp;&nbsp; 日期: 2003-7-30</FONT> 
    </P></TD></TR></TBODY></TABLE></DIV>
<DIV align=center>
<CENTER>
<TABLE border=0 cellPadding=0 cellSpacing=0 height=1 width="96%">
  <TBODY>
  <TR>
    <TD height=1 width="100%">
      <HR color=#396da5 SIZE=3>
    </TD></TR></TBODY></TABLE></CENTER></DIV>
<DIV align=center>
<TABLE border=0 cellPadding=0 cellSpacing=0 class=content height=4300 
width="96%">
  <TBODY>
  <TR>
    <TD height=2132 vAlign=top width="131%">
      <P>&nbsp;&nbsp;&nbsp; Win2k Build 2195 中 EPROCESS 偏移+128 处的 struct 
      HANDLE_TABLE *ObjectTable ,就是指向该进程 HANDLE_TABLE 结构的指针。通过一个进程的 HANDLE_TABLE 
      结构,我们可以找到这个进程打开的所有对象。我们在程序中获得的各种句柄,就是对象在句柄表中的索引。例如,在程序中打开文件,获得的是一个句柄(HANDLE)。接下来通过这个句柄来对这个文件进行操作。句柄是该文件对象在句柄表中的索引,通过句柄,就可以在句柄表中找到相应的文件对象的指针。就可以对该文件对象进行相应的操作。<BR><BR>&nbsp;&nbsp;&nbsp; 
      通过 EPROCESS 的 +128 struct HANDLE_TABLE *ObjectTable 我们可以找到一个进程的 
      HANDLE_TABLE 结构,通过 HANDLE_TABLE 结构的 +08 struct _HANDLE_TABLE_ENTRY 
      ***Table 
      我们可以找到这个进程的句柄表。这个表中放着进程的所有对象的指针。句柄表分三层,最上层表是一个大小为1KB的数组,共有256个元素,每个元素4个字节长,每个元素是一个指向中层表的指针。中层表也是一个大小为1KB的数组,共有256个元素,每个元素4个字节长,每个元素是一个指向下层表的指针。下层表是一个 
      HANDLE_TABLE_ENTRY 数组,整个数组大小为2KB,共有256个元素,每个元素8个字节长,是一个 HANDLE_TABLE_ENTRY 
      ,HANDLE_TABLE_ENTRY 
      中保存着指向对象的指针。一个进程有一个上层表,一个上层表最多可以有256个中层表。每个中层表最多可以有256个下层表。每个下层表最多可以有256个对象的指针。 

      <P>&nbsp;&nbsp;&nbsp; 
      一个句柄被分为三部分,分别做这三个表中的索引,最低10bit(bits0-9)的值乘以2,就得到了在下层表中的偏移。bits10-17这8bit,为中层表的索引,乘以4得到在中层表中的偏移。bits18-25这8bit,为高层表的索引,乘以4得到在高层表中的偏移。<BR><BR>&nbsp;&nbsp;&nbsp; 
      对于一个句柄,我们最后可以在一个下层表中找到对应的 HANDLE_TABLE_ENTRY。HANDLE_TABLE_ENTRY 大小为 8 
      个字节,由2个32bit组成。如果第一个32bit值不为0,那么第一个32bit就可以转换成一个指向对象头的指针。由于对象头总是32bit对齐的,所以一个对象头的指针的低3bit总是0。所以 
      HANDLE_TABLE_ENTRY 第一个32bit 
      的低3bit,被用作标志。由于所有的对象都在系统地址空间(0x80000000-0xFFFFFFFF)中,所以一个对象头的指针的最高位总是1。所以 
      HANDLE_TABLE_ENTRY 第一个32bit 的最高位也被用作标志。当我们把一个<BR>HANDLE_TABLE_ENTRY 
      第一个32bit 
      转换成对象头的指针时,需要把低3bit设为0,最高位设为1。对象指针总是指的对象体的指针,由于对象头在对象体之前,大小为0x18字节,所以对象指针等于对象头指针加0x18。<BR><BR>HANDLE_TABLE 
      结构在 Win2k Build 2195 中定义如下<BR><BR>kd&gt; !strct HANDLE_TABLE<BR>!strct 
      HANDLE_TABLE<BR>struct _HANDLE_TABLE (sizeof=108)<BR>+00 uint32 
      Flags<BR>+04 int32 HandleCount<BR>+08 struct _HANDLE_TABLE_ENTRY 
      ***Table<BR>+0c struct _EPROCESS *QuotaProcess<BR>+10 void 
      *UniqueProcessId<BR>+14 int32 FirstFreeTableEntry<BR>+18 int32 
      NextIndexNeedingPool<BR>+1c struct _ERESOURCE HandleTableLock<BR>+1c 
      struct _LIST_ENTRY SystemResourcesList<BR>+1c struct _LIST_ENTRY 
      *Flink<BR>+20 struct _LIST_ENTRY *Blink<BR>+24 struct _OWNER_ENTRY 
      *OwnerTable<BR>+28 int16 ActiveCount<BR>+2a uint16 Flag<BR>+2c struct 
      _KSEMAPHORE *SharedWaiters<BR>+30 struct _KEVENT *ExclusiveWaiters<BR>+34 
      struct _OWNER_ENTRY OwnerThreads[2]<BR>uint32 OwnerThread<BR>int32 
      OwnerCount<BR>uint32 TableSize<BR>+44 uint32 ContentionCount<BR>+48 uint16 
      NumberOfSharedWaiters<BR>+4a uint16 NumberOfExclusiveWaiters<BR>+4c void 
      *Address<BR>+4c uint32 CreatorBackTraceIndex<BR>+50 uint32 SpinLock<BR>+54 
      struct _LIST_ENTRY HandleTableList<BR>+54 struct _LIST_ENTRY *Flink<BR>+58 
      struct _LIST_ENTRY *Blink<BR>+5c struct _KEVENT 
      HandleContentionEvent<BR>+5c struct _DISPATCHER_HEADER Header<BR>+5c byte 
      Type<BR>+5d byte Absolute<BR>+5e byte Size<BR>+5f byte Inserted<BR>+60 
      int32 SignalState<BR>+64 struct _LIST_ENTRY WaitListHead<BR>+64 struct 
      _LIST_ENTRY *Flink<BR>+68 struct _LIST_ENTRY *Blink<BR><BR>kd&gt; !strct 
      HANDLE_TABLE_ENTRY<BR>!strct HANDLE_TABLE_ENTRY<BR>struct 
      _HANDLE_TABLE_ENTRY (sizeof=8)<BR>+0 void *Object<BR>+0 uint32 
      ObAttributes<BR>+4 uint32 GrantedAccess<BR>+4 uint16 
      GrantedAccessIndex<BR>+6 uint16 CreatorBackTraceIndex<BR>+4 int32 
      NextFreeTableEntry<BR><BR>下面我们使用 kd 来进行说明<BR><BR>kd&gt; !process 0 
      0<BR>!process 0 0<BR>**** NT ACTIVE PROCESS DUMP 
      ****<BR>...<BR><BR>PROCESS 82592ae0 SessionId: 0 Cid: 0254 Peb: 7ffdf000 
      ParentCid: 0240<BR>DirBase: 02611000 ObjectTable: 824e08e8 TableSize: 
      31.<BR>Image: internat.exe<BR>...<BR><BR>// 我们就以进程 internat.exe 为例,注意 
      ObjectTable: 824e08e8 TableSize: 31<BR><BR>// 使用 !handle 命令,查看 PID为254 
      的进程的句柄表中的对象<BR>kd&gt; !handle 0 3 254<BR>!handle 0 3 254<BR>processor 
      number 0<BR>Searching for Process with Cid == 254<BR>PROCESS 82592ae0 
      SessionId: 0 Cid: 0254 Peb: 7ffdf000 ParentCid: 0240<BR>DirBase: 02611000 
      ObjectTable: 824e08e8 TableSize: 31.<BR>Image: internat.exe<BR><BR>Handle 
      Table at e3073000 with 31 Entries in use<BR>0004: Object: e13d7c10 
      GrantedAccess: 000f001f<BR>Object: e13d7c10 Type: (8141b760) 
      Section<BR>ObjectHeader: e13d7bf8<BR>HandleCount: 1 PointerCount: 
      1<BR><BR>0008: Object: 8236a400 GrantedAccess: 00100003<BR>Object: 
      8236a400 Type: (8141e460) Event<BR>ObjectHeader: 8236a3e8<BR>HandleCount: 
      1 PointerCount: 1<BR><BR>...<BR><BR>0044: Object: e139af20 GrantedAccess: 
      000f003f<BR>Object: e139af20 Type: (8141b0c0) Key<BR>ObjectHeader: 
      e139af08<BR>HandleCount: 1 PointerCount: 1<BR>Directory Object: 00000000 
      Name: \REGISTRY\MACHINE<BR>\\ 进程句柄为 0044 的对象,下面我们将自己通过句柄表找到句柄为44的对象<BR>\\ 
      记住对象的名字 Name: \REGISTRY\MACHINE&nbsp;<BR>...<BR><BR>00ac: Object: e3065800 
      GrantedAccess: 00020019<BR>Object: e3065800 Type: (8141b0c0) 
      Key<BR>ObjectHeader: e30657e8<BR>HandleCount: 1 PointerCount: 
      1<BR>Directory Object: 00000000 Name: 
      \REGISTRY\MACHINE\SYSTEM\ControlSet001<BR>\Control\Nls\Language 
      Groups<BR><BR>\\ 首先从进程的 EPROCESS 结构中获得 HANDLE_TABLE 结构的地址<BR>kd&gt; !strct 
      eprocess 82592ae0<BR>!strct eprocess 82592ae0<BR>struct _EPROCESS 
      (sizeof=648)<BR>...<BR>+128 struct _HANDLE_TABLE *ObjectTable = 
      824E08E8<BR>...<BR><BR>\\ 从 HANDLE_TABLE 结构中的 +08 struct 
      _HANDLE_TABLE_ENTRY ***Table 找到句柄表<BR>kd&gt; !strct handle_table 
      824E08E8<BR>!strct handle_table 824E08E8<BR>struct _HANDLE_TABLE 
      (sizeof=108)<BR>+00 uint32 Flags = 00000000<BR>+04 int32 HandleCount = 
      0000001f<BR>+08 struct _HANDLE_TABLE_ENTRY ***Table = E3073000<BR>+0c 
      struct _EPROCESS *QuotaProcess = 82592AE0<BR>+10 void *UniqueProcessId = 
      00000254<BR>+14 int32 FirstFreeTableEntry = 00000021<BR>+18 int32 
      NextIndexNeedingPool = 00000100<BR>...<BR>+54 struct _LIST_ENTRY 
      HandleTableList<BR>+54 struct _LIST_ENTRY *Flink = 835CC9DC<BR>+58 struct 
      _LIST_ENTRY *Blink = 8105449C<BR>+5c struct _KEVENT 
      HandleContentionEvent<BR>...<BR>+68 struct _LIST_ENTRY *Blink = 
      824E094C<BR><BR>句柄表的上层表地址为 E3073000,现在我们开始寻找句柄为 0x44 对应的对象<BR><BR>// 句柄 
      0x44,的上层索引,bits18-25的值为0,偏移为0*4。<BR>// 对应的中层表的地址为 e3073400<BR>kd&gt; dd 
      E3073000+0*4 l 4<BR>dd E3073000+0*4 l 4<BR>e3073000 e3073400 00000000 
      00000000 00000000<BR><BR>// 句柄 0x44,的中层索引,bits10-17的值为0,偏移为0*4。<BR>// 
      对应的下层表的地址为 e3073800<BR>kd&gt; dd e3073400+0*4 l 4<BR>dd e3073400+0*4 l 
      4<BR>e3073400 e3073800 00000000 00000000 00000000<BR><BR>// 句柄 
      0x44,bits0-9的值为0x44, HANDLE_TABLE_ENTRY 在下层表中的偏移为 0x44*2<BR>kd&gt; dd 
      e3073800+44*2 l 8<BR>dd e3073800+44*2 l 8<BR>e3073888 6139af08 000f003f 
      62beecc8 000f003f<BR>e3073898 010e86b8 0002000f 010c9cf8 
      001f0003<BR><BR>我们找到了句柄 0x44 对应的 HANDLE_TABLE_ENTRY,它的第一个32bit,值为 6139af08 
      ,不空。<BR>我们把它转换为对象指针。<BR><BR>// 转换成对象头的指针,把低3bit设为0,最高位设为1。<BR>// 由于 
      6139af08 低三位为0,所以不用设置。最高位不为1,通过加 80000000 ,来设置成1。<BR>kd&gt; ? 
      80000000+6139af08<BR>? 80000000+6139af08<BR>Evaluate expression: 
      -516313336 = e139af08<BR><BR>// 对象指针是对象体的指针,等于对象头指针加0x18<BR>kd&gt; ? 
      e139af08+18<BR>? e139af08+18<BR>Evaluate expression: -516313312 = 
      e139af20<BR><BR>得到了对象指针 e139af20<BR><BR>// 使用 !object 命令,来分析对象。<BR>kd&gt; 
      !object e139af20<BR>!object e139af20<BR>Object: e139af20 Type: (8141b0c0) 
      Key<BR>ObjectHeader: e139af08<BR>HandleCount: 1 PointerCount: 
      1<BR>Directory Object: 00000000 Name: 
      \REGISTRY\MACHINE<BR><BR>可以看到这个对象就是前面使用 !handle 命令时,看到的那个对象。<BR>通过句柄 0x44 
      我们找到了相应的对象。<BR><BR><B>句柄表所消耗的内存</B><BR><BR>当进程打开的对象不超过大约256个时,系统只为句柄表分配一个上层表,大小为1KB。一个中层表,大小为1KB。一个下层表,大小为2KB。正好可以放在同一个物理页中。当进程打开的对象超过大约256个时,系统会再分配2个下层表,放在同一个物理页,并把这2个下层表的地址,填入中层表的相应项,这样就可以存放大约256*3=768 
      个对象的对象头指针。绝大多数情况下,这就够用了。<BR><BR>所以绝大多数情况下,进程的句柄表消耗的物理内存为4K(打开的对象不超过大约256个时)或者8K(打开的对象不超过大约768个时)。<BR><BR>下面我们来看一下刚才进程 
      internat.exe 的句柄表的情况<BR>上层表地址为 e3073000,上层表第一项对应的中层表地址为 
      e3073400,<BR>上层表第一项对应的中层表的第一项对应的下层表地址为 
      e3073800<BR>正是在同一页上,我们显示这一页中的全部内容<BR><BR>kd&gt; dd e3073000 l 400<BR>dd 
      e3073000 l 400<BR>e3073000 e3073400 00000000 00000000 00000000<BR>e3073010 
      00000000 00000000 00000000 00000000<BR>...<BR>e30733f0 00000000 00000000 
      00000000 00000000<BR>e3073400 e3073800 00000000 00000000 
      00000000<BR>e3073410 00000000 00000000 00000000 
      00000000<BR>...<BR>e30737e0 00000000 00000000 00000000 
      00000000<BR>e30737f0 00000000 00000000 00000000 00000000<BR>e3073800 
      00000000 00000001 613d7bf8 000f001f<BR>e3073810 0236a3e8 00100003 01092948 
      00100003<BR>e3073820 02244748 00100003 010f5f18 00000003<BR>e3073830 
      0132a7b2 00100020 010f6878 000f000f<BR>e3073840 021fb2a8 00100003 613b3e19 
      001f0001<BR>e3073850 010e84c8 00000001 61390498 000f001f<BR>e3073860 
      0108a529 001f0003 010c9220 000f037f<BR>e3073870 010c3dc0 000f01ff 010c9220 
      000f037f<BR>e3073880 02469968 00100003 6139af08 000f003f<BR>e3073890 
      62beecc8 000f003f 010e86b8 0002000f<BR>e30738a0 010c9cf8 001f0003 02469d28 
      001f0003<BR>e30738b0 02469ce8 001f0001 02469ca8 001f0003<BR>e30738c0 
      02469c68 001f0001 61371d88 000f003f<BR>e30738d0 6139a508 000f003f 63418e08 
      000f003f<BR>e30738e0 00000000 0000002c 613d20c8 000f0007<BR>e30738f0 
      00000000 0000001c 00000000 00000020<BR>e3073900 00000000 00000023 00000000 
      00000022<BR>e3073910 00000000 00000025 00000000 00000024<BR>e3073920 
      00000000 0000001e 00000000 00000026<BR>e3073930 00000000 00000027 00000000 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -