http://www.vckbase.com/
DUPLICATEHANDLE函数可以实现将同步内核对象被拷贝并且将原内核对象关闭, 从而达到可以自由控制内核对象的目的, 这可以实现使得只能单一启用的进程成为多启用的进程的目的。
实现方法:
只要用钩子WH_GETMESSAGE挂钩并实现如下代码即可
LRESULT HookProc(int code, WPARAM wParam, LPARAM lParam)
{
STARTUPINFO startUpInfo;
GetStartupInfo(&startUpInfo);
char str[MAX_PATH];
LPSTR lpStr = startUpInfo.lpTitle;
if (!g_bFounded)
{
if (lpStr != NULL)
{
_splitpath(lpStr,NULL, NULL, str, NULL);
DWORD iStrLen = MAX_PATH;
DWORD dwRegType = 0;
RegQueryValueExA(HKEY_CURRENT_USER, "PeHook//HookedProcessName", NULL, &dwRegType, (LPBYTE)g_strAppName, &iStrLen);
if (strcmp(str,/*"wmplayer"*/g_strAppName) == 0)
{
HANDLE hToken;
TOKEN_PRIVILEGES tp;
DWORD rl;
BOOL Result = FALSE;
//打开进程令牌环
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
//获得进程本地唯一ID
if (LookupPrivilegeValueA(NULL, "SeDebugPrivilege", &tp.Privileges[0].Luid) )
{
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
//调整权限
Result = AdjustTokenPrivileges(hToken, false, &tp, sizeof(tp), NULL, &rl);
}
if (Result)
{
char buffer[200];
HANDLE hSrcProc = GetCurrentProcess();
DWORD dwError = GetLastError();
HANDLE hSrcHandle = (HANDLE)0x38;
HANDLE hCurProc= GetCurrentProcess();
HANDLE hTargetHandle = 0;
BOOL bRet = DuplicateHandle(hSrcProc, hSrcHandle, hCurProc, &hTargetHandle, DUPLICATE_SAME_ACCESS, FALSE, DUPLICATE_CLOSE_SOURCE);
if (bRet)
{
CloseHandle(hTargetHandle);
g_bFounded = TRUE;
}
}
}
return CallNextHookEx(glhHook,code,wParam,lParam);
}
/
资料:
CSDN: http://cache.baidu.com/c?m=9f65cb4a8c8507ed4fece76310408a23450add306ac0d0622e95c51484642c1d1020fefa7a65505584d87f6001ad4356e8e4732f77552fa0edca9f3caaace22238f92123716c913164c46da5dc3624d651e14de8df0e97bfe74392b9a3a4c82520dd52756df1fa9c290a03bb1be76246&p=8e6ed55f86cc4bf30be2943848&user=baidu
CSDN: http://cache.baidu.com/c?m=9f65cb4a8c8507ed4fece7631046893b4c4380146d96864968d4e414c4224627003ab8f12422141980852d3d5aeb1e41eaf234762a0022aa98cb9549dcba902f2b8e3034074fc70358c75cf28b102a9660d007a9b81897adf74684afa2808e05048b12127bf0e78c2e1715ba39a7486ab4f08e48640252edb17225a2082068de&p=c933891985cc44f508e2937c505d&user=baidu
简单算法遍历PspCidTable句柄表
ULONG GetPspCidTable()
{
ULONG PspCidTable=0;
ULONG FuncAddr=NULL;
UNICODE_STRING FuncName={0};
RtlInitUnicodeString(&FuncName,L"PsLookupProcessByProcessId");
FuncAddr=(ULONG)MmGetSystemRoutineAddress(&FuncName);
for (;;FuncAddr++)
{
if ((0x35ff==(*(PUSHORT)FuncAddr)) && (0xe8==(*(PUCHAR)(FuncAddr+6))))
{
PspCidTable=*(PULONG)(FuncAddr+2);
break;
}
}
return PspCidTable;
}
#define OBJECT_BODY_TO_TYPE 0x10
//从3级表开始遍历
ULONG BrowseTableL3(ULONG TableAddr)
{
ULONG Object=0;
ULONG ItemCount=511;
do
{
TableAddr+=8;
Object=*(PULONG)TableAddr;
Object&=0xfffffff8;
if (Object==0)
{
continue;
}
if ((*PsProcessType)==(*(PULONG)(Object-OBJECT_BODY_TO_TYPE)))
{
KdPrint(("%s",PsGetProcessImageFileName((PEPROCESS)Object)));
}
} while (--ItemCount>0);
return 0;
}
//从二级表开始遍历
ULONG BrowseTableL2(ULONG TableAddr)
{
do
{
BrowseTableL3(*(PULONG)TableAddr);
TableAddr+=4;
} while ((*(PULONG)TableAddr)!=0);
return 0;
}
//从1级表开始遍历
ULONG BrowseTableL1(ULONG TableAddr)
{
do
{
BrowseTableL2(*(PULONG)TableAddr);
TableAddr+=4;
} while ((*(PULONG)TableAddr)!=0);
return 0;
}
VOID RefreshProcessByPspCidTable()
{
ULONG PspCidTable=0;
ULONG HandleTable=0;
ULONG TableCode=0;
ULONG flag=0;
PspCidTable=GetPspCidTable();
HandleTable=*(PULONG)PspCidTable;
TableCode=*(PULONG)HandleTable;
flag=TableCode&3;
TableCode&=0xfffffffc;
switch (flag)
{
case 0:
BrowseTableL3(TableCode);
break;
case 1:
BrowseTableL2(TableCode);
break;
case 2:
BrowseTableL1(TableCode);
break;
}
}
劫持内核句柄
2009-06-17 10:42:42 www.hackbase.com 来源:
看雪
Sysnap 2009,6 为什么需要
句柄?
句柄只是对对像的引用,当我们进入
内核时,获取
对象显然是很简单,但为什么还需要
句柄 呢? 应该说我们需要
句柄做为参数调用API. 因为直接操作
对象,可能会涉及到许多的 ...
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
所以劫持是成功的.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)