进程的来龙去脉

进程的创建是一件相当复杂的事情,其中要包涵很多工作,我们可以通过反汇编来看看CreateProcess()。为了启动一个进程 可有以下几步:

1.可执行文件必须被以FILE_EXECYTE存取方式打开。

2.可执行映像必须被转载进RAM。

3.必须建立进程执行对象(EPROCESS、KPROCESS和PEB结构)。

4.必须为新建进程分配地址空间。

5.必须建立进程的主线程的线程执行对象(ETHREAD、KTHREAD和TEBstructures)。

6.必须为主线程分配堆栈。

7.必须建立进程的主线程的执行上下文。

8.必须通知Win32子系统有关该进程的创建情况。

下面我们来看一看CreateProcess()函数的一些参数

WINBASEAPI
BOOL
WINAPI
CreateProcessA(
    __in_opt       LPCSTR lpApplicationName, //可执行文件的文件名
    __inout_opt LPSTR lpCommandLine, //命令行参数
    __in_opt       LPSECURITY_ATTRIBUTES lpProcessAttributes, //进程的安全属性
    __in_opt       LPSECURITY_ATTRIBUTES lpThreadAttributes, //线程的安全属性
    __in       BOOL bInheritHandles, // 当前进程内的句柄可不可以被子进程继承
    __in       DWORD dwCreationFlags, //这个一会再说
    __in_opt    LPVOID lpEnvironment,  //  是否使用本进程的环境变量,默认为NULL
    __in_opt    LPCSTR lpCurrentDirectory,  // 是否使用本进程的驱动器和目录,默认为NULL
    __in       LPSTARTUPINFOA lpStartupInfo, // 这里边是一个STARTUPINFO结构体的对象
    __out       LPPROCESS_INFORMATION lpProcessInformation // 这里边是一个PROCESS_INFORMATION结构体的对象
    );

STARTUPINFO结构体的具体内容如下:

typedef struct _STARTUPINFO {

    DWORD   cb; // 是本结构的长度 ,一般情况下设为{ sizeof(STARTUOINFO) },为什么呢?原因是因为不同版本的此结构体他们的成员是不一定的
    LPSTR   lpReserved; //  被保留的字段
    LPSTR   lpDesktop; // 指定桌面的名称
    LPSTR   lpTitle; // 控制台应用程序的使用,指定控制台窗口标题

// 指定新创建窗口的位置坐标 和  大小信息
    DWORD   dwX;
    DWORD   dwY;
    DWORD   dwXSize;
    DWORD   dwYSize;


    DWORD   dwXCountChars; // 控制台程序使用,指定控制台窗口的行数
    DWORD   dwYCountChars; // 
    DWORD   dwFillAttribute; // 控制台程序使用,指定控制台窗口的的背景色
    DWORD   dwFlags; // 标志 它的值决定了STARTUPINFO结构中哪个成员是有效的
    WORD    wShowWindow; // 窗口的显示方式
    WORD    cbReserved2; // 
    LPBYTE  lpReserved2; // 
    HANDLE  hStdInput; // 控制台程序使用,几个标准句柄
    HANDLE  hStdOutput; // 
    HANDLE  hStdError; // 
} STARTUPINFOA, *LPSTARTUPINFOA;

PROCESS_INFORMATION结构体的具体内容如下:

typedef struct _PROCESS_INFORMATION {
    HANDLE  hProcess; // 新建进程的内核句柄
    HANDLE  hThread; // 新建进程中主线程的内核句柄
    DWORD  dwProcessId; // 新建进程的ID
    DWORD  dwThreadId; // 新建进程的主线程ID
} PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;

下面贴出一段代码来看看创建进程的实例

#include "windows.h"
#include "iostream"
using namespace std;

int main()
{
	char szCommandLine[]="cmd";
	STARTUPINFO si={sizeof(si)};
	PROCESS_INFORMATION pi;
	si.dwFlags=STARTF_USESHOWWINDOW;
	si.wShowWindow=TRUE;

	BOOL bRet=::CreateProcess(	NULL,
					szCommandLine,
					NULL,
					NULL,
					FALSE,
					CREATE_NEW_CONSOLE,
					NULL,
					NULL,
					&si,
					&pi
				);
	if(bRet)
	{
		::CloseHandle(pi.hThread);
		::CloseHandle(pi.hProcess);
		printf("ProcessID %d \n",pi.dwProcessId);
		printf("ThreadID %d \n",pi.dwThreadId);

	}
	return 0;
}

从CreateProcess()函数的最后两个参数的样子可以看出,&对象,一定是CreateProcess()把一些东西写进对象相应的结构中去了。

下面再来看一小段程序,它主要是用用来枚举系统中正在运行的进程的一些相关的信息

	#include "windows.h"
	#include "tlhelp32.h"
	
	int main()
	{
		
		HANDLE hProcessSnap = NULL;
		PROCESSENTRY32 pe32 = {0};
		//获得句柄
		hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
		if(hProcessSnap == (HANDLE)-1)
		{
			printf("\nCreateToolhelp32Snapshot()failed:%d",GetLastError());
			return;
		}
		pe32.dwSize = sizeof(PROCESSENTRY32);
		
		//列举所有进程名称
		if (Process32First(hProcessSnap, &pe32))
		{
			do
			{
				printf("进程名称 %s 进程ID %u \n",pe32.szExeFile,pe32.th32ProcessID);
			}
			while (Process32Next(hProcessSnap, &pe32));//直到列举完毕
		}
		else
		{
			printf("\nProcess32Firstt() failed:%d",GetLastError());
		}
		//关闭句柄
		CloseHandle (hProcessSnap); 
		return 0;
	}

从倒数第12行可以看出,我们是从pe32对象的th32ProcessID成员中获得到当前系统正在运行的进程的一些信息的。当然了在整个的遍历的过程中,是通过

BOOL WINAPI Process32Next(
__in     HANDLE hSnapshot,
__out    LPPROCESSENTRY32 lppe
);
函数来进行遍历的,当然了他遍历的是系统的快照,其中第一个参数便是一个系统快照的句柄,所以程序的最初是要创建系统快照,目的就是把当前系统内正在运行的进程通过快照捕获下来一份。

我们不得不看看PROCESSENTRY32是一个什么东东,他的内部都有哪些成员,这些成员都存储了什么东西。

typedef struct tagPROCESSENTRY32
{
    DWORD   dwSize; // 结构的长度,不需预先设置
    DWORD   cntUsage; // 进程的引用计数
    DWORD   th32ProcessID;          // this process
    ULONG_PTR th32DefaultHeapID; //进程默认堆的ID
    DWORD   th32ModuleID;           // associated exe进程模块的ID
    DWORD   cntThreads; // 进程创建的线程数
    DWORD   th32ParentProcessID;    // this process's parent process 进程的父线程ID
    LONG    pcPriClassBase;         // Base priority of process's threads 进程创建的线程的基本优先级
    DWORD   dwFlags; // 内部使用
    CHAR    szExeFile[MAX_PATH];    // Path 进程对应的可执行文件名
} PROCESSENTRY32;




未完待续。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值