首页 > 系统相关 >进程的来龙去脉

进程的来龙去脉

时间:2022-11-11 22:36:00浏览次数:38  
标签:__ INFORMATION HANDLE 来龙去脉 句柄 进程 DWORD


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




未完待续。。。。

标签:__,INFORMATION,HANDLE,来龙去脉,句柄,进程,DWORD
From: https://blog.51cto.com/u_15872025/5845489

相关文章

  • 如何在Linux中查找进程
    大多数Linux用户使用预装的默认系统监控工具来检查内存、CPU使用率等。在Linux中,许多应用程序作为守护进程在系统后台运行,这会消耗更多的系统资源。在Linux中,您可以......
  • 遍历PspCidTable表检测隐藏进程
    参考:http://www.alonemonkey.com/details-in-pspcidtbale.html一、PspCidTable概述PspCidTable也是一个句柄表,其格式与普通的句柄表是完全一样的,但它与每个进程私有的句......
  • 进程间通信-信号-pipe-fifo
    一、实验截图(一)fifo(二)pipe(三)signal二、实验代码fifo//consumer#include<stdio.h>#include<stdlib.h>#include<string.h>#include<fcntl.h>#......
  • 【深究】对常驻进程问题再剖析
    工作中的难点问题正是我们知识技术栈全谱查漏补缺的最佳机遇,有问题不可怕,allin、死磕就完事了,哈哈哈~一问题回顾启动进程时,shm_attach()方法报错:failedforkey0x6104e88......
  • 获取系统所有进程
    //进程获取publicvoidmpid()throwsIOException{Stringname=ManagementFactory.getRuntimeMXBean().getName();//System.out.println(name);Strin......
  • ulimit命令优化linux进程连接数等…
    在Linux下面部署应用的时候,有时候会遇上Socket/File:Can’topensomanyfiles的问题,比如还有Squid做代理,当文件打开数到900多时速能就非常快的下降,有可能打不开网页.其......
  • 进程间通信-信号-pipe-fifo
    进程间通信-信号-pipe-fifo一、信号signal代码1.sigactdemo.c#include<stdio.h>#include<unistd.h>#include<signal.h>#define INPUTLEN 100voidinthandler();int......
  • 关于 Android 应用多进程的整理
    在计算机操作系统中,进程是进行资源分配和调度的基本单位。这对于基于Linux内核的Android系统也不例外。在Android的设计中,一个应用默认有一个(主)进程。但是我们通过配置可......
  • IIS7中asp.net执行cmd命令提示:拒绝访问。安全狗-》安全防护-》去掉勾选“进程行为控
    研究了一下午,怎么也没想到这里有个坑。。。安全狗-》安全防护-》去掉勾选“进程行为控制”     无法执行CMD的解决办法: ......
  • Linux Supervisor 进程管理工具安装及使用
    Supervisor是用Python开发的进程管理工具,可以很方便的用来启动、重启、关闭进程(不仅仅是Python进程)。能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出......