《Windows核心编程》第3章——深入理解handle

2021-07-02 07:05

阅读:409

标签:net   类型   value   目标   bug   .net   流程   结果   arch   

本文借助windbg来理解程序中的函数如何使用handle对句柄表进行查询的。所以先要开启Win7下Windbg的内和调试功能。

  • 解决win7下内核调试的问题
win7下debug默认无法进行内核调试(!process等命令无法使用),除非是双机调试。或改用livekd进行调试。
尝试http://blog.csdn.net/hutao1101175783/article/details/50522767中提出的方法,开启windbg的内和调试功能:
技术分享图片

重启之后开启Local Kernel Debugging:

技术分享图片

技术分享图片

开启成功:

技术分享图片

加载符号表之后,就可以使用!process命令了:

 技术分享图片

  • 解决windbg源码调试的问题:

 添加源文件路径:

 技术分享图片

开启源码级别的调试:

技术分享图片

给TestHandle.exe的main函数下断点:
技术分享图片
运行后自动弹出源码调试:

 技术分享图片

  • 研究句柄 

 再开一个windbg用内核调试。!process 0 0 命令找到TestHandle.exe的信息:

技术分享图片

查看这个进程的所有句柄信息(同时也显示出了OBJECT的信息,来给我们提供验证):

 技术分享图片

下面,借助对TestHandle.exe的调试我们知道38号句柄是hEvent:

技术分享图片

查看0x38号句柄的信息(这个信息被我当做“结果”来验证我的“推理”过程):

技术分享图片

  • 推理步骤

 查看TestHandle的EProcess结构:

 技术分享图片

得到TableCode,这个值指向一级、二级或三级句柄表(具体是几级句柄表由末尾数决定):

 技术分享图片

根据低两位判断句柄表的层级。TableCode低位是1,说明是一个二级句柄表(可以参考这个文章的分析:https://www.cnblogs.com/lsh123/p/7296423.html):

 技术分享图片
这里显示了两个一级句柄表
不同级别的句柄表可以参考文章:https://www.2cto.com/kf/201609/543902.html
和图:
技术分享图片

那么句柄值乘以4再加上fffff8a0`19ca8000就是指向对应的handle_table_entry://为什么这里要乘以4?句柄是0x38,索引就是0x38/4,又由于每个handle_table_entry的大小是16字节。那么为什么索引是0x38/4?后面会回答

 找到对应的handle_table_entry:

技术分享图片

其中fffffa80`11399951 就是Object指针,偏移0x30-1就可以定位到OBJECT:

 技术分享图片

因为是在64位系统下,所以偏移是0x30-1,偏移发生了变化(32位系统下就是0x17):

技术分享图片

这样就通过句柄取到了内核对象,整个流程思路参考了:http://www.cppblog.com/sleepwom/archive/2011/10/19/72591.html
并参考了图片:
技术分享图片

 

  •  handle的类型

 

在WinNT.h中定义的handle是这样的:
typedef void* handle;

 技术分享图片

而DECLARE_HANDLE(HWND);就是:
  struct HWND__ { int unused;};
  typedef struct HWND__ *HWND;
所以DECLARE_HANDLE的作用就是将name定义为一个指向结构体的指针。
handle是一个无类型指针,而HWND是一个指向结构体的指针。
Handle是一个void存储着一个整形数据类型作为“伪索引”。
参考:https://www.cnblogs.com/zpcdbky/p/4656449.html
http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece7631046893b4c4380143fd3d1027fa3c215cc79051a0071e4cf6678475886d27b135bfc1541baae6b272a4266e4dd93d957deb0902f248b2631701c844213d719a9c84524c627935ee3aa04f3ffad72c5a1888083020d9d44050bc2b4d60156&p=c449ca5f86cc41ac52a5d02d021494&newp=81798f16d9c111a058ee9e124f43c9231610db2151d4d2116b82c825d7331b001c3bbfb423251007d7c07d6304aa4858eff6357033092ba3dda5c91d9fb4c57479&user=baidu&fm=sc&query=handle+pvoid&qid=b9f8680100001e9b&p1=5
 
  • 为什么要除以4?
如果要根据句柄查找相应的handle_table_entry,就会调用这个函数:
ExMapHandleToPointer ( __in PHANDLE_TABLE HandleTable, __in HANDLE Handle )

 

这里的handle就是我们本例中传入的0x38。ExMapHandleToPointer 中又会调用ExpLookupHandleTableEntry。
在使用句柄去查找进程的句柄表时会调用函数ExpLookupHandleTableEntry,其原型如下:

 技术分享图片

参数 HandleTable 是查找目标所在的 Handle table 地址,而 tHandle 是结构化的 Handle 值。参考:http://www.soscw.com/info-detail-1539980.html
handle与exhandle的关系如下:
技术分享图片
这个 tHandle 结构将 Handle 值分为几个部分,如下图所示:

 技术分享图片

这个 TagBit 值占两位(bit 0 到 bit 1),被清为 0 值。因此:tHandle.Value 值就是对齐在 4 bytes 边界上。(出于某种原因)使用高30位作为索引来查找句柄表,低两位的存在没有意义。参考:https://www.cnblogs.com/ck1020/p/5897460.html

 现在低两位没有意义不代表将来低两位没有意义,handle的含义和使用可能在未来发生变化。

《Windows核心编程》第3章——深入理解handle

标签:net   类型   value   目标   bug   .net   流程   结果   arch   

原文地址:https://www.cnblogs.com/adylee/p/9934751.html


评论


亲,登录后才可以留言!