首页
社区
课程
招聘
未解决 [求助]内核层如何检查进程是否已经结束?(已解决,感谢大佬)
发表于: 2020-11-7 23:15 3014

未解决 [求助]内核层如何检查进程是否已经结束?(已解决,感谢大佬)

2020-11-7 23:15
3014

调用 PsLookupProcessByProcessId 这个函数的时候,进程存在和存在过但已结束状态下都会返回成功,要怎么判断进程是否处于已终止状态?


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2020-11-9 18:46 被大佬求关照编辑 ,原因: 已解决
收藏
免费 0
支持
分享
最新回复 (7)
雪    币: 12356
活跃值: (5879)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
2

最靠谱的方法,NtQuerySystemInformation的ProcessAndThreadInformation列举的进程ID全部都是有效进程,其他各种硬编码找信息的都是玩蛇

最后于 2020-11-7 23:44 被hhkqqs编辑 ,原因:
2020-11-7 23:43
0
雪    币: 2674
活跃值: (2304)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
3

这里还是给个已导出但未公开的内核API:ZwQuerySystemInformation获取系统进程的例子片段给楼主.后续的应该可以搞定了!
注意: 调用Zwxxx的函数中断级通常规定是PASSIVE_LEVEL
//用于ZwQuerySystemInformation函数信息类型参数
typedef enum _SYSTEM_INFORMATION_CLASS{
    SystemBasicInformation,
    SystemProcessorInformation,
    SystemPerformanceInformation,
    SystemTimeOfDayInformation,
    SystemPathInformation,
    SystemProcessInformation,   //5
    SystemCallCountInformation,
    SystemDeviceInformation,
    SystemProcessorPerformanceInformation,
    SystemFlagsInformation,
    SystemCallTimeInformation,
    SystemModuleInformation   //11
}SYSTEM_INFORMATION_CLASS;

//SystemProcessInformation进程信息结构体定义(32位,64位均可用) ,每条进程信息长度不固定 ,需要根据NextEntryOffset定位下一条
//如果NextEntryOffset==0,则说明已是最后一个进程了
typedef struct _SYSTEM_PROCESS_INFORMATION {
    ULONG                   NextEntryOffset; 
    ULONG                   NumberOfThreads;
    ULONG                   Reserved1[6];
    LARGE_INTEGER           CreateTime;
    LARGE_INTEGER           UserTime;
    LARGE_INTEGER           KernelTime;
    UNICODE_STRING          ImageName;
    ULONG                   BasePriority;
    HANDLE                  UniqueProcessId;
    HANDLE                  InheritedFromProcessId;
    ULONG                   HandleCount;
    UCHAR                   Reserved2[4];
    PVOID                   Reserved3[11];
    SIZE_T                  PeakPagefileUsage;
    SIZE_T                  PrivatePageCount;
    LARGE_INTEGER           Reserved4[6];
    UCHAR                             Others[1]; 
}SYSTEM_PROCESS_INFORMATION,*PSYSTEM_PROCESS_INFORMATION;

//ZwQuerySystemInformation函数指针
typedef NTSTATUS(NTAPI *lpfnZwQuerySystemInformation)(
       IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
       IN OUT PVOID SystemInformation,
       IN ULONG SystemInformationLength,
       OUT PULONG ReturnLength OPTIONAL
);

通用获取系统进程的例子片段:
//ZwQuerySystemInformation函数入口地址
RtlInitUnicodeString(&unsFuncName,
       L"ZwQuerySystemInformation");
g_userGlobalInfo.g_ZwQuerySystemInformation=(lpfnZwQuerySystemInformation)MmGetSystemRoutineAddress(&unsFuncName);
KdPrintEx((
    DPFLTR_IHVDRIVER_ID,
    DEBUG_LEVEL,
    "ZwQuerySystemInformation addr: 0x%p\n",
     g_userGlobalInfo.g_ZwQuerySystemInformation
));
...
PSYSTEM_PROCESS_INFORMATION pSysProcInfos=NULL, pCurSysProcInfos;
ULONG ulBufLen,ulRetLen;
NTSTATUS ntStatus=STATUS_UNSUCCESSFUL;
do{
    ..
    ulBufLen=PAGE_SIZE;
        
      //分配缓冲区
      pSysProcInfos=(PSYSTEM_PROCESS_INFORMATION)ExAllocatePoolWithTag(PagedPool,
                       (SIZE_T)ulBufLen,
                       MYTAG);
       if(pSysProcInfos==NULL){
         ntStatus=STATUS_INSUFFICIENT_RESOURCES;
                  break;
       }

       //尝试性获取系统中的进程
       ulRetLen=0;
       ntStatus=pUserGlobalInfo->g_ZwQuerySystemInformation(SystemProcessInformation,
           (PVOID)pSysProcInfos,
            ulBufLen,
            &ulRetLen);
       if(!NT_SUCCESS(ntStatus)){
       if(ntStatus!=STATUS_INFO_LENGTH_MISMATCH&&ntStatus!=STATUS_BUFFER_TOO_SMALL){
            break;
       }
       if(ulRetLen==0){
           break;
       }
            
       //重新分配缓冲区
       ExFreePoolWithTag((PVOID)pSysProcInfos,
               MYTAG);
       ulBufLen=ulRetLen+PAGE_SIZE; //grab
       pSysProcInfos=(PSYSTEM_PROCESS_INFORMATION)ExAllocatePoolWithTag(PagedPool,
               (SIZE_T)ulBufLen,
               MYTAG);
       if(pSysProcInfos==NULL){
           ntStatus=STATUS_INSUFFICIENT_RESOURCES;
           break;
       }

       //再次获取系统中的进程
       ulRetLen=0;
                ntStatus=pUserGlobalInfo->g_ZwQuerySystemInformation(SystemProcessInformation,
                               (PVOID)pSysProcInfos,
                               ulBufLen,
                               &ulRetLen);
       if(!NT_SUCCESS(ntStatus)){
           break;
       }
       }

    ...
}while(FALSE);

if(NT_SUCCESS(ntStatus)){
     //获取系统进程成功
            for(pCurSysProcInfos=pSysProcInfos;
            pCurSysProcInfos->NextEntryOffset>0;
            pCurSysProcInfos=(PSYSTEM_PROCESS_INFORMATION) 
            ((PUCHAR)pCurSysProcInfos+pCurSysProcInfos->NextEntryOffset)){
             //检查进程ID
             ...
         }
        //检查最后1个进程ID
        ....

}
if(pSysProcInfos!=NULL){
       ExFreePoolWithTag((PVOID)pSysProcInfos,
           MYTAG);
}

最后于 2020-11-8 00:26 被低调putchar编辑 ,原因:
2020-11-8 00:25
0
雪    币: 2674
活跃值: (2304)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
hhkqqs 最靠谱的方法,NtQuerySystemInformation的ProcessAndThreadInformation列举的进程ID全部都是有效进程,其他各种硬编码找信息的都是玩蛇
2楼的大神还不睡觉吗?
2020-11-8 00:27
0
雪    币: 12356
活跃值: (5879)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
5
低调putchar 2楼的大神还不睡觉吗?[em_13]
您才是真正的大神,我随便回个帖的功夫,您都贴上源码了
2020-11-8 00:46
0
雪    币: 4006
活跃值: (726)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
6
BOOLEAN BBCheckProcessTermination( PEPROCESS pProcess )
{
    LARGE_INTEGER zeroTime = { 0 };
    return KeWaitForSingleObject( pProcess, Executive, KernelMode, FALSE, &zeroTime ) == STATUS_WAIT_0;
} ---blackbone
2020-11-8 02:50
0
雪    币: 2055
活跃值: (486)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
7

(PsGetProcessExitStatus(LsProcess)==0x103) 图方便一直这么判断 没出过啥问题 不等于103就退出

最后于 2020-11-8 08:26 被不吃麻婆豆腐编辑 ,原因:
2020-11-8 08:26
1
雪    币: 6
活跃值: (556)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
低调putchar 这里还是给个已导出但未公开的内核API:ZwQuerySystemInformation获取系统进程的例子片段给楼主.后续的应该可以搞定了!注意: 调用Zwxxx的函数中断级通常规定 ...
感谢大佬,已经成功解决
2020-11-9 18:45
0
游客
登录 | 注册 方可回帖
返回
//