0
点赞
收藏
分享

微信扫一扫

进程的来龙去脉


进程的创建是一件相当复杂的事情,其中要包涵很多工作,我们可以通过反汇编来看看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 {

// 是本结构的长度 ,一般情况下设为{ 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​


​);​


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


我们不得不看看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;




未完待续。。。。

举报

相关推荐

0 条评论