pspCidTAble完全解读

上传人:cl****1 文档编号:571267849 上传时间:2024-08-09 格式:PDF 页数:12 大小:810.51KB
返回 下载 相关 举报
pspCidTAble完全解读_第1页
第1页 / 共12页
pspCidTAble完全解读_第2页
第2页 / 共12页
pspCidTAble完全解读_第3页
第3页 / 共12页
pspCidTAble完全解读_第4页
第4页 / 共12页
pspCidTAble完全解读_第5页
第5页 / 共12页
点击查看更多>>
资源描述

《pspCidTAble完全解读》由会员分享,可在线阅读,更多相关《pspCidTAble完全解读(12页珍藏版)》请在金锄头文库上搜索。

1、欢迎您阅读并下载本文档,本文档来源于互联网,如有侵权请联系删除!我们将竭诚为您提供优质的文档!PspCidTable 完全解读 by sysdog 2009.5.1 Whu - 一、句柄 句柄:HADNLE 在 winnt.h 定义如下: typedef void *HANDLE; 是一个 32 位无类型指针,充当内核对象在内核的索引. 句柄本质内核对象(object)的索引 每个进程都有自己的进程句柄表,当操作进程对象时,会把对象指针放在自己的句柄表中,返回一个句柄,通过句柄来索引对象指针,然后操作对象。 进程句柄表是根据 HANDLE 索引对象指针的,而 pspcidtable(未导出,需

2、要自己定位地址)是根据 CID 索引对象指针的. EPROCESS 和 ETHREAD 分别是进程对象和线程对象 用户空间 内核空间 内核对象 NT 内核 NT 执行体 执行体对象 HANDLE (句柄) 应用程序 图一、句柄、NT 执行体对象和 NT 内核对象 I欢迎您阅读并下载本文档,本文档来源于互联网,如有侵权请联系删除!我们将竭诚为您提供优质的文档!PspCidTable 完全解读 by sysdog 2009.5.1 Whu - 用户空间 内核空间 EPROCESS (进程对象) ETHREAD (线程对象) KTHREAD (线程描述表) KPROCESS (PCB) (进程描述表

3、) NT 执行体 NT 内核 图二、进程和线程描述表 NT 执行体处理进程线程对象,进程和线程描述表可由 EPROCESS 结构来访问,NT 内核处理进程和线程描述表 二、句柄表 XP 下句柄表是动态分配的,是个三层表,1级表(称为基本表)存放系统底层的。 句柄表大小为 1 页即 4K,而每个表项是一个 HANDLE_TABLE_ENTRY 占 8 个字节,所以每个表最多只能放 512 个表项,又因为表项索引是以 4 递增的,因此一个最终表能承受的最大索引值也是 2048 即 0x800,两个表最大为 0x1000,三个表就是 0x1800。 句柄表的格式如下: PspCidTable 完全解

4、读 by sysdog 2009.5.1 Whu - II欢迎您阅读并下载本文档,本文档来源于互联网,如有侵权请联系删除!我们将竭诚为您提供优质的文档!句柄表就是 HANDLE_TABLE 结构,如下: 里面没有指针结构啊,那么句柄表到底存储在那里? 实际是保存在 TableCode 里面,但是 TableCode 并不是地址,它比地址所担任的责任多一 点:标明这个指针指向的是哪一级别的句柄,在 x86 上面 Windows 总是分配内存使其沿四个字节对齐,所以实际的句柄表地址的低两位一定是 0? 。XP 就用这两位来标示这个表是哪个级别,00 表示 1 级表,01 表示 2 级表,02 表示

5、 3 级表。2 级表存放的是 1 级表的指针,3 级表存放的是 2 级表的指针。 TableCode 转变一下就是 HANDLE_TABLE_ENTRY 了,转变也很简单,就是低两位清零,因为底两位代表当前句柄表的级数,HANDLE_TABLE 里面存放的是一些信息,HANDLE_TABLE_ENTRY 才是真正的句柄表。 HANDLE_TABLE_ENTRY 结构如下: 如果是一级表 HANDLE_TABLE_ENTRY=TableCode 如果是二级表 HANDLE_TABLE_ENTRY 需要根据 2 级表中的指针来找 1 级表的基址, 然后再根据 1 级表中的偏移找到进程对象.三级表类

6、推 III欢迎您阅读并下载本文档,本文档来源于互联网,如有侵权请联系删除!我们将竭诚为您提供优质的文档! 三、内核对象 作为一个 Wi n d o w s 软件开发人员,经常需要创建、打开和操作各种内核对象。系统要创 建和操作若干类型的内核对象,比如存取符号对象、事件对象、文件对象、文件映射对象、 I / O 完成端口对象、作业对象、信箱对象、互斥对象、管道对象、进程对象、信标对象、线程对象和等待计时器对象等。 这些对象都是通过调用函数来创建的。 例如, C r e a t e F i l e M a p p i n g 函数可使系统能够创建一个文件映射对象。 每个内核对象只是内核分配的一个内

7、存块,并且只能由该内核访问。该内存块是一种数据结构,它的成员负责维护该对象的各种信息。有些数据成员(如安全性描述符、使用计数等)在所有对象类型中是相同的,但大多数数据成员属于定的对象类型。例如,进程对象有一个进程 I D、一个基本优先级和一个退出 代码,而文件对象则拥有一个字节位移、一个共享模式和一个打开模式。由于内核对象的数据结构只能被内核访问,因此应用程序无法在内存中找到这些数据结构并直接改变它们的内容。M i c r o s o f t 规定了这个限制条件,目的是为了确保内核对象结构保持状态的一致。这个限制也使 M i c r o s o f t 能够在不破坏任何应用程序的情况下在这些结

8、构中添加、 删除和修改数据成员。如果我们不能直接改变这些数据结构,那么我们的应用程序如何才能操作这些内核对象呢?解决办法是,Wi n d o w s 提供了一组函数,以便用定义得很好的方法来对这些结构进行操作。这些内核对象始终都可以通过这些函数进行访问。当调用一个用于创建内核对象的函数时, 该函数就返回一个用于标识该对象的句柄。该句柄可以被视为一个不透明值,你的进程中的任何线程都可以使用这个值。将这个句柄传递给 Wi n d o w s 的各个函数,这样,系统就能知道你想操作哪个内核对象。 四、PspCidTable 对象指针:从其线形地址来看,它将常驻内存的结构体划分为两部分:一个对象头和一

9、个对象体。对象指针并没有指向对象自身的基地址,而是指向了对象体,由于紧接着对象头的就是对象体,所以可以给对象指针加上一个负的偏移量来访问对象头。 IV欢迎您阅读并下载本文档,本文档来源于互联网,如有侵权请联系删除!我们将竭诚为您提供优质的文档! 对象 对象指针 对象头(Object Header) 对象体(Object) 根据 HANDLE 索引句柄对象体过程 EPROCESS HANDLE_TABLE 对象 根据 HANDLE 索引对象头 Object Table TableCode Object Header Object 通过 PID 索引进程对象体过程 HANDLE_TABLE 索引

10、HANDLE_TABLE_ENTRY PID EPROCESS Object TableCode PspCidTable V欢迎您阅读并下载本文档,本文档来源于互联网,如有侵权请联系删除!我们将竭诚为您提供优质的文档! PspCidTable:指向 HANDLE_TABLE 的指针,未导出结构,存放所有进程及线程对象指针。 指针 lkd dt _handle_table ntdll!_HANDLE_TABLE +0x000 TableCode +0x004 QuotaProcess +0x008 UniqueProcessId +0x00c HandleTableLock +0x01c Han

11、dleTableList +0x024 HandleContentionEvent +0x028 DebugInfo +0x02c ExtraInfoPages +0x030 FirstFree +0x034 LastFree +0x038 NextHandleNeedingPool +0x03c HandleCount +0x040 Flags +0x040 StrictFIFO PspCidTable PspCidTable 是一个句柄表,其格式与普通的句柄表是完全一样的.但它与每个进程私有的句柄表有以下不同: 1.PspCidTable 中存放的对象是系统中所有的进线程对象指针,其索引就

12、是 PID 和 CID 2.PspCidTable中存放是对象体(指向EPROCESS和ETHREAD),而每个进程私有的句柄表则存放的是对象头(OBJECT_HEADER) 3.PspCidTable是一个独立的句柄表,而每个进程私有的句柄表以一个双链连接起来 PspCidTable在 XP 下是个三层表,动态分配的 PspCidTable 是内核未导出的 HANDLE_TABLE 结构,它保存着所有进程及线程对象指针.只要可以遍历这个表就可以遍历所有进程,包括隐藏进程(hook ZWQuerySystemInformation) ,抹除 PspCidTable 除外,下面根据 KD 查看此

13、表: VI欢迎您阅读并下载本文档,本文档来源于互联网,如有侵权请联系删除!我们将竭诚为您提供优质的文档!图一 通过 PspCidTable 遍历进程就是为了获取进程对象指针。PspCidTable 是根据 PID 或者 CID索引的,所以就依据进程 CID 获取进程对象指针。 五、演示说明 1.根据 HANDLE 索引 object 指针 ObjectTable: e7313480利用 Local kernel 来验证,查找 0x14 句柄的对象指针 PROCESS 88cb7020ObjectTable: e7313480 0014: Object: e1c050d0Name: Window

14、s PspCidTable 完全解读 by sysdog 2009.5.1 Whu - 注意红色部分。ObjectTable: e7313480指向 HANDLE_TABLE 结构 TableCode : 0xe5018000 QuotaProcess : 0x88cb7020 _EPROCESS VII欢迎您阅读并下载本文档,本文档来源于互联网,如有侵权请联系删除!我们将竭诚为您提供优质的文档!TableCode: 0xe5018000 最低两位为 00 表示 0 级表。于是查找句柄为 0x14 的对象指针 有(因为索引时按 4 递增的,一个 HANDLE_TABLE_ENTRYA 占 8

15、个字节) Ptr=HANDLE_TABLE_ENTRY+HANDLE*8/4= HANDLE_TABLE_ENTRY+HANDLE*2 e1c050b9 看到e1c050b9就是0x14对应的object Header, 这里需要转换一下 (低三位清零再加上Object Header 大小,因为 object header 是 8 个字节对齐,低三位做标志位) Object=object Header&0xfffffff8+sizeof(Object Header) e1c050b9 & 0xfffffff8 + 0x18=e1c050d0- Object: e1c050d0 Name: Wi

16、ndows 跟上面的一模一样。 2.根据 CID 索引(PspCidTable 句柄表)对象指针 首先是查找 pspcidtable 句柄表的地址: e1002ca8 00000002 00000001 00000000 然后观察 HANDLE_TABLE 结构: VIII欢迎您阅读并下载本文档,本文档来源于互联网,如有侵权请联系删除!我们将竭诚为您提供优质的文档!TableCode : 0xe3a39001 NextHandleNeedingPool : 0x1000 TableCode=e3a39001 第二位为 01 表示有 2 层表。 NextHandleNeedingPool : 0

17、x1000 ,该字段说明了当 PID 或 CID 达到多少以上时,需要再建立一个新表(最终表) 。我们的系统里现在已经有两个最终表了。最终表大小为 1 页即 4K,而每个表项是一个 HANDLE_TABLE_ENTRY 占 8 个字节,所以每个表最多只能放 512 个表项,又因为表项是用 PID 或者 TID 来索引的,而索引是以 4 递增的,因此一个最终表能承受的最大 ID 也是 2048 即 0x800,两个表最大为 0x1000,以此类推. e1005000 TableCode=e3a39001 可知道:有 2 个基本表 一级表中放的是基本表的指针 0 级表的 HANDLE_TABLE_

18、ENTRY= e1005000 计算公式: PHANDLE_TABLE_ENTRY =HANDLE_TABLE_ENTRY+CID*sizeof(HANDLE_TABLE_ENTRY)/PID_INC 即 PHANDLE_TABLE_ENTRY = HANDLE_TABLE_ENTRY+CID*2 IX欢迎您阅读并下载本文档,本文档来源于互联网,如有侵权请联系删除!我们将竭诚为您提供优质的文档!对 CID=0x16C0x800 88cb7020e7313480208. 下面对这个进行验证。 由于 CID0x800 88cc78b0 CID800 说明在 1 级表中 PHANDLE_TABLE_

19、ENTRY = e3a39000+984*2(e3a3a000+184*2) 0x88cc78b1 得到 EPROCESS 的地址为 0x88cc78b1& (3)= 0x88cc78b0,验证正确。 X欢迎您阅读并下载本文档,本文档来源于互联网,如有侵权请联系删除!我们将竭诚为您提供优质的文档! PspCidTable 完全解读 by sysdog 2009.5.1 Whu - 六、基于 PspCidTable 的进程检测及隐藏技术分析 1.基于 HOOK 的检测技术:遍历 PspCidTable 所有进程对象指针 由于 PspCidTable 是未导出结构,需要自己定位 【一】PspCid

20、Tble 的定位 1.PsLookupProcessByProcessId(PsLookupThreadByThreadId 或者 PsLookupProcessThreadByCid)函数中搜索 特征串(0x35ff 和 0x8e)定位 PspCidTalbe CODE: 2.利用 KDDEBUGGER_DATA(32/64)结构得到 pspCidTable KdEnableDebugger-KdInitSystem-KdDebuggerDataBlock-KDDEBUGGER_DATA32-PspCidTable 3. 利用 KPCR 中取,KRCR 地址 ffdff000 处是一个叫做

21、KPCR 的结构,PCR 即 Processor Control Region ,处理器控制域。这是一个很有用的结构。系统本身就大量使用。0xffdff000 是 KPCR 这个结构变量的地址 那么+0x34 就是 KdVersionBlock 成员变量在该结构中的偏移 但是在 0xffdff034 指向的地方对应有个结构_DBGKD_GET_VERSION64 可惜的是这个结构只有 0x28 字节大小 但是.嘿嘿 这个结构后面藏着 N 多超级重要的内核变量。我们的 pspcidtable 这个变量其实就在这个结构起始位置的 0x80 字节偏移处 XI欢迎您阅读并下载本文档,本文档来源于互联网,如有侵权请联系删除!我们将竭诚为您提供优质的文档! XII 【二】进程对象的遍历 1.利用未导出的 ExEnumHandleTable 函数 2.直接自己获取 PHANDLE_TABLE_ENTRY 等,然后 PsLookupProcessByProcessId 3. 自己写实现遍历(完成) 2.隐藏技术:抹掉 PspCidTable 表 (完成) 3.基于抹掉 PspCidTable 的进程检测技术(正在调试) 七、几种隐藏进程技术分析及对策 没开始写呢

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 建筑/环境 > 施工组织

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号