首页
论坛
课程
招聘
[原创]劫持内核句柄
2009-6-13 12:13 11424

[原创]劫持内核句柄

2009-6-13 12:13
11424
Sysnap 2009,6

为什么需要句柄?
句柄只是对对像的引用,当我们进入内核时,获取对象显然是很简单,但为什么还需要句柄

呢? 应该说我们需要句柄做为参数调用API. 因为直接操作对象,可能会涉及到许多的未导

出的东西,如果自己实现的话是不大现实,而调用标准的内核API又很多时候依赖于句柄,但

又很多时候因为种种原因,我们得不到句柄,这里我们将探讨下怎样获取一个有用的句柄.

任何问题欢迎指正: http://hi.baidu.com/sysnap/blog

1 句柄的创建
ObpCreateHandle 这个函数会判断AccessMode,如果是用户态的,那PVOID ObjectTable;
ObjectTable = PsGetCurrentProcess()->ObjectTable
如果是在驱动中打开句柄,则ObjectTable = ObpKernelHandleTable;
ObpKernelHandleTable是一个指向HANDLE_TABLE的指针,在系统中并没有导出
接着便会ATTACH 到SYSTEM进程..
调用ObpIncrementHandleCount增添Object引用数,这个地方我们慢点再考虑有没必要做一

些工作.
调用ExCreateHandle 创建句柄,ExCreateHandle中调用
//// 分配一个HANDLE_TABLE_ENTRY和一个句柄,这个句柄的值的产生是在
///ExpAllocateHandleTableEntry中完成的.
ExpAllocateHandleTableEntry 是句柄分配的核心,也涉及到了相关的数据结构.但这里我

们可以不用管它.
我们只需要知道ObpCreateHandle会给我们返回一和句柄,并且会在ObjectTable新添加一

个HANDLE_TABLE_ENTRY
lkd> dt _HANDLE_TABLE_ENTRY
nt!_HANDLE_TABLE_ENTRY
   +0x000 Object           : Ptr32 Void
HANDLE_TABLE_ENTRY 就包含有我们的Object了.

2 句柄到OBJECT的映射
这里涉及到了句柄表的格式,关于句柄表,网上已经有相关的文章讨论了,这里将不再说
typedef struct _EXHANDLE     
{   
    union     
    {   
        struct     
        {   
            ULONG TagBits : 02;   
            ULONG Index   : 30;   
        };   
   
        HANDLE GenericHandleOverlay;   
    };   
   
} EXHANDLE, *PEXHANDLE;

可以看出,一个类型为HANDLE的,其实分为俩部分,TagBits和Index,具体干什么,请看下面

的函数
PHANDLE_TABLE_ENTRY     
    LookupHandleTableEntry(   
               IN PXP_HANDLE_TABLE HandleTable,   
               IN EXHANDLE         Handle   
               )   
{   
    ULONG i, j, k;   
    PHANDLE_TABLE_ENTRY Entry = NULL;   
    ULONG TableCode = HandleTable->TableCode& ~TABLE_LEVEL_MASK;   
   
    i = (Handle.Index >> 17) &0x1FF;   
    j = (Handle.Index >> 9)  &0x1FF;   
    k = (Handle.Index)       &0x1FF;   
   
    switch (HandleTable->TableCode &TABLE_LEVEL_MASK)   
    {   
        case 0 :   
          Entry = &((PHANDLE_TABLE_ENTRY)TableCode)[k];   
        break;   
            
        case 1 :   
          if (((PVOID *)TableCode)[j])     
          {   
             Entry = &((PHANDLE_TABLE_ENTRY *)TableCode)[j][k];            
          }   
        break;   
        case 2 :   
          if (((PVOID *)TableCode)[i])   
          if (((PVOID **)TableCode)[i][j])   
          {   
             Entry = &((PHANDLE_TABLE_ENTRY **)TableCode)[i][j][k];            

              
          }   
        break;   
    }   
    return Entry;   
}

这样的话我们就可以根据HANDLE..获取到HANDLE_TABLE_ENTRY从而得到Object
上面的函数只适合XP和2003

3句柄的权限
如果我们想修改某个句柄的权限,可以通过HANDLE_TABLE_ENTRY::GrantedAccess

4ObOpenObjectByPointer
ObReferenceObjectByPointer添加计数
ObpCreateHandle句柄的创建

5怎样伪造.
比如我们想伪造一个XX.EXE进程的句柄.

1首先我们需要确定 ObpKernelHandleTable
        DWORD dwObpKernelHandleTable = 0;
        PVOID lpPsSystemObject = (PVOID)PsGetCurrentProcess();
        dwObpKernelHandleTable = *(DWORD*)((DWORD)lpPsSystemObject +

gdwObjectTableOffset);

2 ObOpenObjectByPointer 打开explorer.exe (这里随便找个没保护的进程就可以)
获取句柄 hProcess
3 用某些办法获取XX.EXE 的进程对象EPROCESS
4 用hProcess为参数调用,LookupHandleTableEntry得到一个指向PHANDLE_TABLE_ENTRY的

指针pEntry
这个时候pEntry->Object应该就是 explorer.exe的EPRCESS
5 修改pEntry->Object = XX.EXE的EPROCESS
这样我们就完成了HANDLE和OBJECT的劫持..

这都是主要步骤,其中有些细节问题需要注意,比如增加对象的句柄数啊等等.

6 有效果吗?
我们知道大部分内核API都会以一个HANDLE做为参数的,其内部基本都是调用了

ObReferenceObjectByHandle来定位对象,我们分析下ObReferenceObjectByHandle就知道

我们的劫持是否有用了.
很显然ObReferenceObjectByHandle是根据 HANDLE_TABLE来把句柄转化为对象,过程简单

为 handle--->> pEntry->Object
所以劫持是成功的.
这就是我的思路,有什么问题大家可以指正,谢谢.
参考资料:
[1] WRK
[2] PsCidTable相关文章

看雪社区年底排行榜,查查你的排名?

收藏
点赞0
打赏
分享
最新回复 (16)
雪    币: 15
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xiaojiuhk 活跃值 2009-6-13 12:14
2
0
很不错的文章~
雪    币: 213
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
绿豆青蛙 活跃值 2009-6-13 12:41
3
0
学习了,句柄也给劫持了。。。
雪    币: 392
活跃值: 活跃值 (10)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
ImHolly 活跃值 1 2009-6-13 13:34
4
0
内核中这种劫持有很多。

问下楼主的那个调试器弄得怎么样了
雪    币: 7502
活跃值: 活跃值 (112)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
achillis 活跃值 15 2009-6-13 14:13
5
0
感觉好像意义不大啊~
雪    币: 441
活跃值: 活跃值 (43)
能力值: ( LV12,RANK:600 )
在线值:
发帖
回帖
粉丝
Sysnap 活跃值 14 2009-6-13 15:18
6
0
事实上不仅可以内核态的句柄重定向...用户态的也可以....这样我们可以读写内存了...当然还有很多事情可以做...
雪    币: 441
活跃值: 活跃值 (43)
能力值: ( LV12,RANK:600 )
在线值:
发帖
回帖
粉丝
Sysnap 活跃值 14 2009-6-13 15:21
7
0
俺那个内核调试器很久没弄了....面对Syser和Windbg强大的功能// 目前实现了一个内核调试器应有的功能...显视,键盘,鼠标驱动....还有一些简单的命令....感觉没弄下去的必要....
雪    币: 459
活跃值: 活跃值 (38)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
qihoocom 活跃值 9 2009-6-13 17:41
8
0
意义何在?搞不清楚
雪    币: 392
活跃值: 活跃值 (10)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
ImHolly 活跃值 1 2009-6-13 18:47
9
0
其实我很期待你的那个调试器啊
能学习到很多相当底层的东西.
雪    币: 211
活跃值: 活跃值 (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
dayed 活跃值 1 2009-6-13 22:56
10
0
我想到些邪恶的事
雪    币: 441
活跃值: 活跃值 (43)
能力值: ( LV12,RANK:600 )
在线值:
发帖
回帖
粉丝
Sysnap 活跃值 14 2009-6-13 22:58
11
0
呵呵...再想想有很多东西,,,,....实际上可以做XXX重定向...
雪    币: 7502
活跃值: 活跃值 (112)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
achillis 活跃值 15 2009-6-13 23:18
12
0
主要是觉得句柄的产生和销毁是动态的,临时性的东西,搞起来有意义吗?
雪    币: 231
活跃值: 活跃值 (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
yaolibing 活跃值 2009-6-14 00:29
13
0
请问下Sysnap,有几个问题不是很理解
2 ObOpenObjectByPointer 打开explorer.exe (这里随便找个没保护的进程就可以)
获取句柄 hProcess (这是不是在system进程的句柄表中加入一项HANDLE_TABLE_ENTRY结构并返回句柄hProcess)

6 有效果吗?
我们知道大部分内核API都会以一个HANDLE做为参数的,其内部基本都是调用了

ObReferenceObjectByHandle来定位对象,我们分析下ObReferenceObjectByHandle就知道

我们的劫持是否有用了.
这里的ObReferenceObjectByHandle()系统函数的当前进程是不是也是system.exe进程。
雪    币: 441
活跃值: 活跃值 (43)
能力值: ( LV12,RANK:600 )
在线值:
发帖
回帖
粉丝
Sysnap 活跃值 14 2009-6-14 08:43
14
0
1主要是System进程有一些句柄是固定的...还有其他进程一些也是固定的,比如什么同步用的XX...
2我们自己打开一个对象的句柄,不关闭它,把对像重定向到另外一个对象,这样我们对该句柄的操作都是操作了另外一个对象,,,
雪    币: 7502
活跃值: 活跃值 (112)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
achillis 活跃值 15 2009-6-14 10:44
15
0
ring0下搞这些操作都很容易啊,如果说用它搞一些XX的话,都驱了有什么不能搞,犯不着在句柄上折腾…也许你说的第一条还稍有点意义~
雪    币: 8658
活跃值: 活跃值 (365)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
cvcvxk 活跃值 10 2009-6-14 10:50
16
0
很意思,一个假的可用进程啊~
雪    币: 303
活跃值: 活跃值 (10)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
寂寞羽毛 活跃值 1 2009-6-14 22:09
17
0
好文章哦..
游客
登录 | 注册 方可回帖
返回