利用psapi.dll提供的API枚举进程--Ring3枚举进程

   日期:2020-05-11     浏览:117    评论:0    
核心提示:按照惯例,先来看一下EnumProcesses的底层实现到底是个什么东东??其实其内部还是调用了Nt系列的函数,通过宏传递参数,查询各种信息。最终返出各个进程的ID值BOOLWINAPIEnumProcesses(DWORD *lpidProcess, DWORD cb, LPDWORD lpcbNeeded){ NTSTATUS Status; DWORD Size = MAXSHORT, Count; PSYSTEM数据结构与算法

按照惯例,先来看一下EnumProcesses的底层实现到底是个什么东东??其实其内部还是调用了Nt系列的函数,通过宏传递参数,查询各种信息。最终返出各个进程的ID值

BOOL
WINAPI
EnumProcesses(DWORD *lpidProcess,
              DWORD cb,
              LPDWORD lpcbNeeded)
{
    NTSTATUS Status;
    DWORD Size = MAXSHORT, Count;
    PSYSTEM_PROCESS_INFORMATION ProcInfo;//先定义两个结构体用来承接NtQuerySystemInformation系列的返回值
    PSYSTEM_PROCESS_INFORMATION ProcInfoArray;

    
    do
    {
    //申请内存
        ProcInfoArray = LocalAlloc(LMEM_FIXED, Size);
        if (ProcInfoArray == NULL)
        {
            return FALSE;
        }
	//查询进程信息
        Status = NtQuerySystemInformation(SystemProcessInformation, ProcInfoArray, Size, NULL);
        if (Status == STATUS_INFO_LENGTH_MISMATCH)
        {
        //如果内存长度不够,释放,继续申请
            LocalFree(ProcInfoArray);
            Size += MAXSHORT;
            continue;
        }
		//查询结束
        break;
    }
    while (TRUE);

    if (!NT_SUCCESS(Status))
    {
    //若Status返回值失败,则设置错误码,结束函数
        LocalFree(ProcInfoArray);
        SetLastError(RtlNtStatusToDosError(Status));
        return FALSE;
    }

    
    Count = 0;
    ProcInfo = ProcInfoArray;

    _SEH2_TRY
    {
        do
        {
            
            if (Count < cb / sizeof(DWORD))
            {
            //保存id值
                lpidProcess[Count] = (DWORD)ProcInfo->UniqueProcessId;
                Count++;
            }

            if (ProcInfo->NextEntryOffset == 0)
            {
            //如果进程链表结束,则退出
                break;
            }
			//遍历所有进程
            ProcInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcInfo + ProcInfo->NextEntryOffset);
        }
        while (TRUE);

        *lpcbNeeded = Count * sizeof(DWORD);
    }
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
        SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode()));
        LocalFree(ProcInfoArray);
        _SEH2_YIELD(return FALSE);
    }
    _SEH2_END;
	//释放内存,返回成功
    LocalFree(ProcInfoArray);
    return TRUE;
}

EnumProcess使用举例:
通过进程ImageName得到进程ID

ULONG GetActiveProcessIdW(wchar_t* ImageName)
{

	int i;
	wchar_t* TranslatedProcessName;
	DWORD    ProcessId[1024] = {};
	wchar_t  ProcessFullPath[1024] = {};
	DWORD    IsNeeded = NULL;
	HANDLE	 ProcessHandle;
	wchar_t* NameOnly = 0;//只有进程名,没有完整路径

	if (EnumProcesses(ProcessId, sizeof(ProcessId), &IsNeeded))
	{
		for (i = 0; i < (int)(IsNeeded / sizeof(DWORD)); i++)
		{
			if (ProcessId[i] != NULL)
			{
				//提升权限,打开进程
				ProcessHandle = KtOpenProcess(PROCESS_QUERY_INFORMATION,
					false,
					ProcessId[i]);
				if (ProcessHandle != NULL)
				{
					if (GetProcessImageFileNameW(ProcessHandle,
						ProcessFullPath,
						_countof(ProcessFullPath)) > NULL)
					{
						TranslatedProcessName = (wchar_t*)TranslateNativeNameW(ProcessFullPath);
						lstrcpyW(ProcessFullPath, TranslatedProcessName);
						VirtualFree((void*)TranslatedProcessName, NULL, MEM_RELEASE);
						KtCloseHandle(ProcessHandle);

						if (_wcsicmp(ProcessFullPath, ImageName) == 0)
						{
							//如果不匹配,说明传的参数不是完整路径
							return ProcessId[i];
						}
						else
						{
							//寻找最后一个'\'的位置
							NameOnly = wcsrchr(ProcessFullPath, L'\\');
							if (NameOnly)
							{
								//越过'\'
								NameOnly++;
								if (_wcsicmp(NameOnly, ImageName) == 0)
								{
									return ProcessId[i];
								}
							}
						}
					}
					else
					{
						KtCloseHandle(ProcessHandle);
					}
				}
			}
		}
	}
	return NULL;
}

越过山丘,会看见美景依旧!
参考资料:
Reactos

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服