HANDLE LzOpenProcess(DWORD dwDesiredAccess,BOOL bInheritHandle, DWORD dwProcessId)
{
NTSTATUS status=0;
char *pBuf=NULL;
BOOLEAN wasEnabled;
DWORD buflen=0x10000,needlen=0;
DWORD HandleCnt=0;
HANDLE hRetProcess=0,hOwnerProc,hTmp;
PSYSTEM_HANDLE_INFORMATION pSysHandleInfo=NULL;
PROCESS_BASIC_INFORMATION BasePsInfo;
OBJECT_ATTRIBUTES objatr;
CLIENT_ID Cid;
//提升调试权限,否则有些进程,比如服务进程打不开
RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE,TRUE,FALSE,&wasEnabled);
InitializeObjectAttributes(&objatr,0,0,0,0);
//先尝试正常方式打开
Cid.UniqueProcess=(HANDLE)dwProcessId;
Cid.UniqueThread=0;
/*status=ZwOpenProcess(&hRetProcess,dwDesiredAccess,&objatr,&Cid);//尝试直接打开
if (NT_SUCCESS(status))
{
return hRetProcess;
}
//不成功,尝试把PID加1再打开,加2,加3也可以
//理由:有些HOOK函数中过滤PID时不完善,正确的做法应该是先用掩码忽略低两位之后再比较
Cid.UniqueProcess=(HANDLE)(dwProcessId+1);
status=ZwOpenProcess(&hRetProcess,dwDesiredAccess,&objatr,&Cid);//尝试直接打开pid+1
if (NT_SUCCESS(status))
{
return hRetProcess;
}
*/
//都不成功,就找别的进程中的Handle,这才是本代码的核心, 这些Handle大部分是在Csrss.exe中
do
{
//申请查询句柄信息所需的内存
ZwAllocateVirtualMemory(NtCurrentProcess(),(PVOID*)&pBuf,0,&buflen,MEM_COMMIT,PAGE_READWRITE);
//查询系统句柄信息,类型为16
status=ZwQuerySystemInformation(SystemHandleInformation,(PVOID)pBuf,buflen,&needlen);
if (status==STATUS_SUCCESS)
{
break;
}
//不成功,则释放内存
//这里只要一块大内存够放这些内容就行,或者直接申请一块足够大的也可以
//返回的needlen可以做为参考
ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&pBuf,&buflen,MEM_RELEASE);
//然后把要申请的内存大小乘2,直至成功为止
buflen*=2;
pBuf=NULL;
} while(1);
//返回的缓冲区内容的第一个DWORD是总的句柄的个数
HandleCnt=*(DWORD*)pBuf;
//跳过句柄计数,才是真正的开始
pSysHandleInfo=(PSYSTEM_HANDLE_INFORMATION)((char*)pBuf+sizeof(DWORD));
for (DWORD i=0;i<HandleCnt;i++)
{
//只验证类型为PROCESS的,值为5
if (pSysHandleInfo->ObjectTypeNumber==OB_TYPE_PROCESS)
{
//打开这个句柄的所有者进程,要复制过来才能查询,否则只能看不能摸~
Cid.UniqueProcess=(HANDLE)(pSysHandleInfo->ProcessId);
Cid.UniqueThread=0;
status=ZwOpenProcess(&hOwnerProc,PROCESS_ALL_ACCESS,&objatr,&Cid);
if (NT_SUCCESS(status))
{
printf("打开进程成功\n");
//打开成功,复制句柄到本进程,这里用了PROCESS_ALL_ACCESS以避免权限问题
status=ZwDuplicateObject(hOwnerProc,
(HANDLE)(pSysHandleInfo->Handle),
NtCurrentProcess(),
&hTmp,
PROCESS_ALL_ACCESS,
FALSE,
0);
if (NT_SUCCESS(status))
{
printf("复制句柄成功\n");
//复制成功,查询此句柄所对应的进程PID,查询基本信息即可
status=ZwQueryInformationProcess(hTmp,ProcessBasicInformation,&BasePsInfo,sizeof(PROCESS_BASIC_INFORMATION),NULL);
if (NT_SUCCESS(status))
{
//成功,判断其PID
if (BasePsInfo.UniqueProcessId==dwProcessId)
{
//句柄所有者是我们要的目标进程,再按所需的权限复制过来
ZwDuplicateObject(hOwnerProc,
(HANDLE)(pSysHandleInfo->Handle),
NtCurrentProcess(),
&hRetProcess,
0,
FALSE,
PROCESS_ALL_ACCESS);
//关掉为复制而打开的句柄所有者的句柄引用
ZwClose(hOwnerProc);
break;
}
}
}
}
}
pSysHandleInfo++;//指向下一个结构
}
if (pBuf)
{
ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&pBuf,&buflen,MEM_RELEASE);
}
return hRetProcess;
}
这段代码在XP系统下正常,在32位WIN7系统下就无法使用ZwDuplicateObject复制其他进程中的句柄,提升自身进程权限为Debug权限也是一样失败。何故?
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!