首页
社区
课程
招聘
获取指定进程的STARTUPINFO
发表于: 2013-7-22 15:21 7470

获取指定进程的STARTUPINFO

2013-7-22 15:21
7470
我们使用CreateProcess()的时候,指定了一个参数STARTUPINFO,现在我有一个程序我需要获取到其他应用程序的STARTUPINFO,有什么解决方法吗?还望高手指点

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

收藏
免费 0
支持
分享
最新回复 (10)
雪    币: 29214
活跃值: (7719)
能力值: ( LV15,RANK:3306 )
在线值:
发帖
回帖
粉丝
2
先用ZwQueryInformationProcess获取指定进程的PEB, 再从PEB中读取StartupInfo参数(可以参考GetStartupInfo)
2013-7-22 15:54
0
雪    币: 9
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
这个过程有点曲折吧,简单点说,能拿到StartInfo中的lpDesktop就行了
2013-7-22 17:37
0
雪    币: 29214
活跃值: (7719)
能力值: ( LV15,RANK:3306 )
在线值:
发帖
回帖
粉丝
4
自己mark下, 不知道有什么更简单的方法
#include <windows.h>
#include <tchar.h>

int _tmain(int argc, _TCHAR* argv[])
{
	TCHAR szCmd[MAX_PATH] = TEXT("c:\\windows\\notepad.exe");
	TCHAR szDesktop[MAX_PATH] = TEXT("TEST1234567");
	STARTUPINFO si = {0};
	PROCESS_INFORMATION pi = {0};
	
	// desktop must be created before CreateProcess under win7
	CreateDesktop(szDesktop, NULL, NULL, 0, GENERIC_ALL, NULL);
	
	si.cb = sizeof(si);
	si.lpDesktop = szDesktop;

	CreateProcess(NULL, szCmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);

	// wait until resources needed by child process being loaded
	WaitForSingleObject(pi.hProcess, 3000);
	return 0;
}


#include <windows.h>
#include <stdio.h>

#define STATUS_INFO_LENGTH_MISMATCH			((NTSTATUS)0xC0000004L)
#define NT_SUCCESS(status)					((NTSTATUS)(status) == 0)

typedef LONG    NTSTATUS;
typedef ULONG    ACCESS_MASK;

typedef struct _UNICODE_STRING {
	USHORT Length;
	USHORT MaximumLength;
	PWSTR  Buffer;
} UNICODE_STRING;

typedef enum _SYSTEM_INFORMATION_CLASS
{
	SystemHandleInformation = 16,
} SYSTEM_INFORMATION_CLASS;

typedef struct _SYSTEM_HANDLE_INFORMATION
{
	ULONG ProcessId;
	UCHAR ObjectTypeNumber;
	UCHAR Flags;
	USHORT Handle;
	PVOID Object;
	ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;

typedef enum _OBJECT_INFORMATION_CLASS {
	ObjectNameInformation = 1,
	ObjectTypeInformation = 2,
} OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS;

typedef NTSTATUS (WINAPI *ZWQUERYSYSTEMINFORMATION)(
	SYSTEM_INFORMATION_CLASS SystemInformationClass,
	PVOID SystemInformation,
	ULONG SystemInformationLength,
	PULONG ReturnLength
	);

typedef NTSTATUS (WINAPI *NTQUERYOBJECT)(
	HANDLE Handle,
	OBJECT_INFORMATION_CLASS ObjectInformationClass,
	PVOID ObjectInformation,
	ULONG ObjectInformationLength,
	PULONG ReturnLength
	);

typedef struct _OBJECT_NAME_INFORMATION {
	UNICODE_STRING          Name;
	WCHAR                   NameBuffer[1];
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;

typedef enum _POOL_TYPE { 
	NonPagedPool = 0,
} POOL_TYPE;

typedef struct _OBJECT_TYPE_INFORMATION {
	UNICODE_STRING          TypeName;
	ULONG                   TotalNumberOfHandles;
	ULONG                   TotalNumberOfObjects;
	WCHAR                   Unused1[8];
	ULONG                   HighWaterNumberOfHandles;
	ULONG                   HighWaterNumberOfObjects;
	WCHAR                   Unused2[8];
	ACCESS_MASK             InvalidAttributes;
	GENERIC_MAPPING         GenericMapping;
	ACCESS_MASK             ValidAttributes;
	BOOLEAN                 SecurityRequired;
	BOOLEAN                 MaintainHandleCount;
	USHORT                  MaintainTypeList;
	POOL_TYPE               PoolType;
	ULONG                   DefaultPagedPoolCharge;
	ULONG                   DefaultNonPagedPoolCharge;
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;

BOOL EnablePriv(LPCTSTR lpName)
{
	HANDLE hToken;
	TOKEN_PRIVILEGES tp;
	LUID luid;

	if(!::OpenProcessToken(::GetCurrentProcess(),
		TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
		&hToken))
	{
		return FALSE;
	}

	if(!LookupPrivilegeValue(NULL, lpName, &luid))
	{
		return FALSE;
	}

	tp.PrivilegeCount = 1;
	tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	tp.Privileges[0].Luid = luid;

	if(!AdjustTokenPrivileges(hToken, 0, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
	{
		return FALSE;
	}

	return TRUE;
}

BOOL EnumProcessHandle(DWORD ProcessId)
{
	BOOL bRet = FALSE;
	HMODULE hNtDll = NULL;
	ZWQUERYSYSTEMINFORMATION pfnZwQuerySystemInformation = NULL;
	NTQUERYOBJECT pfnNtQueryObject = NULL;
	PSYSTEM_HANDLE_INFORMATION pSysHandleInfo = NULL; 
	POBJECT_NAME_INFORMATION pNameInfo = NULL;
	POBJECT_TYPE_INFORMATION pTypeInfo = NULL;

	ULONG nHandleCount = 0;
	NTSTATUS ntStatus = 0;
	ULONG ulSize;
	ULONG ulBufSize;
	char *cBuffer = NULL;
	char cInfoBuffer[0x10000];
	char cTypeBuffer[0x10000];

	do 
	{
		hNtDll = GetModuleHandle(TEXT("ntdll.dll"));
		if (hNtDll == NULL)
		{
			break;
		}

		pfnZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION)GetProcAddress(hNtDll,"ZwQuerySystemInformation");
		pfnNtQueryObject = (NTQUERYOBJECT)GetProcAddress(hNtDll,"NtQueryObject");

		if (pfnZwQuerySystemInformation == NULL)
		{
			break;
		}
		if (pfnNtQueryObject == NULL)
		{
			break;
		}

		ulBufSize = 0x80000;
		ntStatus = STATUS_INFO_LENGTH_MISMATCH;
		while (true)
		{
			cBuffer = (char *)calloc(1, ulBufSize);
			if (cBuffer == NULL)
			{
				break;
			}
			ntStatus = pfnZwQuerySystemInformation(SystemHandleInformation, cBuffer, ulBufSize, &ulSize);
			if (NT_SUCCESS(ntStatus))
			{
				break;
			}
			if (ntStatus != STATUS_INFO_LENGTH_MISMATCH)
			{
				break;
			}
			free(cBuffer);
			cBuffer = NULL;
			ulBufSize *= 2;
		}
		if (!NT_SUCCESS(ntStatus))
		{
			break;
		}

		nHandleCount = *(PULONG)cBuffer;
		pSysHandleInfo = (PSYSTEM_HANDLE_INFORMATION)(cBuffer + 4);
		for(ULONG i = 0; i < nHandleCount; ++i)
		{
			if(pSysHandleInfo[i].ProcessId != ProcessId)
			{
				continue;
			}

			HANDLE hTargetProcess = OpenProcess(PROCESS_VM_WRITE | PROCESS_DUP_HANDLE, FALSE, GetCurrentProcessId());
			HANDLE hTargetHandle = NULL;
			HANDLE hSourceProcess = OpenProcess(PROCESS_VM_READ | PROCESS_DUP_HANDLE, FALSE, ProcessId);
			HANDLE hSourceHandle = (HANDLE)pSysHandleInfo[i].Handle;

			if (hSourceProcess == NULL)
			{
				continue;
			}

			if (!DuplicateHandle(
				hSourceProcess, 
				hSourceHandle, 
				hTargetProcess, 
				&hTargetHandle, 
				PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, 
				FALSE, 
				0))
			{
				continue;
			}

			ntStatus = pfnNtQueryObject(hTargetHandle, ObjectNameInformation, cInfoBuffer, 0x10000, &ulSize);
			if (!NT_SUCCESS(ntStatus))
			{
				continue;
			}
			pNameInfo = (POBJECT_NAME_INFORMATION)cInfoBuffer;

			ntStatus = pfnNtQueryObject(hTargetHandle, ObjectTypeInformation, cTypeBuffer, 0x10000, &ulSize);
			if (!NT_SUCCESS(ntStatus))
			{
				continue;
			}
			pTypeInfo = (POBJECT_TYPE_INFORMATION)cTypeBuffer;

			//wprintf(L"handle: %08X, type: %s, name: %s\n", hSourceHandle, pTypeInfo->TypeName.Buffer, pNameInfo->NameBuffer);
			if (wcscmp(pTypeInfo->TypeName.Buffer, L"Desktop") == 0)
			{
				wprintf(L"name: %s\n", pNameInfo->NameBuffer + 1);
			}
		}
		bRet = TRUE;
	} while (0);

	return bRet;
}

void main( )
{
	DWORD dwProcessId = 8800;
	do 
	{
		if (!EnablePriv(SE_DEBUG_NAME))
		{
			break;
		}
		if (!EnumProcessHandle(dwProcessId))
		{
			break;
		}
	} while (0);
}
2013-7-22 21:05
0
雪    币: 9
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
我测试了单个进程ID,程序能正常使用,但是我尝试如下方法,程序会莫名卡死
        HANDLE hProSnap;
	HANDLE handle;
	hProSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
	PROCESSENTRY32 Pe; 
	Pe.dwSize=sizeof(PROCESSENTRY32); 
	BOOL return_value;
	return_value = Process32First(hProSnap,&Pe);
	while(return_value)
	{
		
		if(EnumProcessHandle(Pe.th32ProcessID))
		{

			handle=OpenProcess(PROCESS_TERMINATE,TRUE,Pe.th32ProcessID);
			if (handle!=NULL)
				TerminateProcess(handle,0);

		}
		return_value = Process32Next(hProSnap,&Pe);
	}
	CloseHandle(hProSnap);
2013-7-23 14:08
0
雪    币: 3
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
菜鸟进来学习,C#写多了,C不怎么写了,完全忘记了
2013-7-23 14:34
0
雪    币: 9
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
我已经找到解决方法了,通过进行线程快照找到对应进程ID的主线程,使用GetThreadDesktop可以取得桌面句柄,然后使用GetUserObjectInformation()参数指定为UIO_NAME即可获得桌面名称,可能我之前问题没有描述清楚,谢谢风间仁童鞋的耐心回答,表示学习了。也谢谢陈心童鞋的关注,结贴
2013-7-24 10:10
0
雪    币: 29214
活跃值: (7719)
能力值: ( LV15,RANK:3306 )
在线值:
发帖
回帖
粉丝
8
问下LZ, GetThreadDesktop可以返回进程X(假设Desktop为TEST1234)的的桌面句柄吗(假设查询进程的Desktop为Default),
我之前测试的情况是在没有OpenDesktop(TEST1234)的情况下, GetThreadDesktop总是会失败的
2013-7-24 11:51
0
雪    币: 9
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
通过进程X的ID,然后快照线程查找与该进程相关的线程,再通过GetTreadDesktop(线程ID)取得桌面句柄,MSDN上描述GetThreadDesktop的参数可以是CreateProcess的返回的值,但事实上直接调用会提示参数错误。通过线程ID可以正常取得
	HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);
	if( Thread32First( hThreadSnap, &te32) )
	{
		do{
			if( dwProcessID == te32.th32OwnerProcessID )
			{
				dwThreadID = te32.th32ThreadID;
				hTempDesktop = GetThreadDesktop(dwThreadID);
				char name[100];
				DWORD dwLengthNeed;
				if(GetUserObjectInformationA(hTempDesktop, UOI_NAME, name, 1024, &dwLengthNeed))
				{
					DWORD errocode = GetLastError();
					if (0 == lstrcmpA(name,pszDesktopName))
					{
						handle=OpenProcess(PROCESS_TERMINATE,TRUE,dwProcessID);
						if (handle!=NULL)
							if(TerminateProcess(handle,0))
								return TRUE;
					}
				}
	
			}
		}while( Thread32Next( hThreadSnap, &te32) );
2013-7-24 15:10
0
雪    币: 29214
活跃值: (7719)
能力值: ( LV15,RANK:3306 )
在线值:
发帖
回帖
粉丝
10
thx, 了解了
LZ这段代码, 看来是已知desktop name了,
在这段代码执行之前想必已经OpenDesktop或者CreateDesktop了, 不然GetThreadDesktop也会失败的.
我这前的想法都是基于不知道desktop name的情况..
2013-7-24 16:59
0
雪    币: 9
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
Desktop  name是未知的,我是遍历了所有进程,然后查找所有进程的线程,GetThreadDesktop传线程的ID是没有问题,能正确返回
2013-7-25 10:29
0
游客
登录 | 注册 方可回帖
返回
//