-
-
[原创]劫持内核句柄
-
发表于:
2009-6-13 12:13
13950
-
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相关文章
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课