本文借助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存储着一个整形数据类型作为“伪索引”。
这里的handle就是我们本例中传入的0x38。ExMapHandleToPointer 中又会调用ExpLookupHandleTableEntry。
在使用句柄去查找进程的句柄表时会调用函数ExpLookupHandleTableEntry,其原型如下:

参数 HandleTable 是查找目标所在的 Handle table 地址,而 tHandle 是结构化的 Handle 值。参考:http://www.mamicode.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的更多相关文章

  1. windows核心编程 第8章201页旋转锁的代码在新版Visual Studio运行问题

    // 全局变量,用于指示共享的资源是否在使用 BOOL g_fResourceInUse = FALSE; void Func1() { //等待访问资源 while(InterlockedExcha ...

  2. windows核心编程 第5章job lab示例程序 解决小技巧

    看到windows核心编程 第5章的最后一节,发现job lab例子程序不能在我的系统(win8下)正常运行,总是提示“进程在一个作业里”         用process explorer程序查看 ...

  3. windows核心编程---第七章 用户模式下的线程同步

    用户模式下的线程同步 系统中的线程必须访问系统资源,如堆.串口.文件.窗口以及其他资源.如果一个线程独占了对某个资源的访问,其他线程就无法完成工作.我们也必须限制线程在任何时刻都能访问任何资源.比如在 ...

  4. Windows核心编程 第十七章 -内存映射文件(上)

    第1 7章 内存映射文件 对文件进行操作几乎是所有应用程序都必须进行的,并且这常常是人们争论的一个问题.应用程序究竟是应该打开文件,读取文件并关闭文件,还是打开文件,然后使用一种缓冲算法,从文件的各个 ...

  5. Windows核心编程 第六章 线程基础知识 (上)

    第6章 线程的基础知识 理解线程是非常关键的,因为每个进程至少需要一个线程.本章将更加详细地介绍线程的知识.尤其是要讲述进程与线程之间存在多大的差别,它们各自具有什么作用.还要介绍系统如何使用线程内核 ...

  6. Windows核心编程 第四章 进程(上)

    第4章 进 程     本章介绍系统如何管理所有正在运行的应用程序.首先讲述什么是进程,以及系统如何创建进程内核对象,以便管理每个进程.然后将说明如何使用相关的内核对象来对进程进行操作.接着,要介绍进 ...

  7. Windows核心编程 第三章 内核对象

    第3章内核对象 在介绍Windows API的时候,首先要讲述内核对象以及它们的句柄.本章将要介绍一些比较抽象的概念,在此并不讨论某个特定内核对象的特性,相反只是介绍适用于所有内核对象的特性. 首先介 ...

  8. windows核心编程---第四章 进程

    上一章介绍了内核对象,这一节开始就要不断接触各种内核对象了.首先要给大家介绍的是进程内核对象.进程大家都不陌生,它是资源和分配的基本单位,而进程内核对象就是与进程相关联的一个数据结构.操作系统内核通过 ...

  9. Windows核心编程 第27章 硬件输入模型和局部输入状态

    第27章 硬件输入模型和局部输入状态 这章说的是按键和鼠标事件是如何进入系统并发送给适当的窗口过程的.微软设计输入模型的一个主要目标就是为了保证一个线程的动作不要对其他线程的动作产生不好的影响. 27 ...

  10. Windows核心编程 第十七章 -内存映射文件(下)

    17.3 使用内存映射文件 若要使用内存映射文件,必须执行下列操作步骤: 1) 创建或打开一个文件内核对象,该对象用于标识磁盘上你想用作内存映射文件的文件. 2) 创建一个文件映射内核对象,告诉系统该 ...

随机推荐

  1. 2019-04-08-day027-网络编程基础

    网络编程 基于同一台机器上的多个程序之间通信 可以基于文件 基于多台机器之间的通信 可以基于网络 web程序两种架构完成的: C/S :client(客户端) server(服务端) B/S :bro ...

  2. Java学习笔记10(面对对象:构造方法)

    在开发中经常需要在创建初始化对象时候明确对象的属性值, 比如Person对象创建的时候就给Person的属性name,age赋值, 这里就要用到构造方法: 构造方法是类的一种特殊方法,它的特殊性体现在 ...

  3. Diamorphine rootkit的使用

    仅作LKM rootkit研究之用,滥用后果自负. 查看支持版本是否为2.6.x/3.x/4.x: uname -r 下载代码: git clone https://github.com/m0nad/ ...

  4. ORACLE函数、连接查询、约束

    *ORDER BY 子句在SELECT语句的结尾. 使用外连接可以查询不满足连接条件的数据 with字句 字符函数lower upper initcap concat substr length in ...

  5. 【图像基础】图像不变性特征HU矩和Zernike矩

    参考 1. 图像不变性特征: 2. matlab实现: 3. HU矩和Zernike矩: 完

  6. Java中的数组初探

    1.数组的类型? Java中的数组为引用类型. 2.数组的三种初始化方式 1. int[] arr1=new int[] {1,2,3,4,}; 2. int[] arr2= {1,2,3,4,}; ...

  7. Redis同时删除多个key(linux环境下)

    登录redis命令行 #del key1 key2 key3 进入redis命令安装目录 #./redis-cli KEYS "PHPREDIS_SESSION*" | awk ' ...

  8. ElasticSearch 从零到入门

    摘自:https://www.cnblogs.com/keme/p/10108918.html

  9. java实现图片上传功能,并返回图片保存路径

    1.前端html <div class="form-group">     <label for="inputPassword3" class ...

  10. MVC分别代表的含义

    MVC 是一种将应用程序的逻辑层和表现层进行分离的方法.ThinkPHP 也是基于MVC设计模式的.MVC只是一个抽象的概念,并没有特别明确的规定,ThinkPHP中的MVC分层大致体现在:模型(M) ...