Win32 2

铁佛  金牌会员 | 2023-7-16 02:58:48 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 545|帖子 545|积分 1635

5、进程

进程是指运行中的一个程序。(X)
①什么是进程?  进程提供程序所需的资源,如:数据、代码等等。
程序运行起的状态与进程没有关系,举个例子,程序就相当于一个房子,进程就是其中的东西,而使用这些房子中的东西的人称为线程。
②进程内存空间的地址划分
分区 x86 32位Windows  空指针赋值区 0x00000000 -0x0000FFFF //操作系统都没有使用的空间 用户模式区 0x00010000-0x7FFEFFFF  64KB禁入区  0x7FFF0000-0x7FFFFFFF 内核 0x80000000-0xFFFFFFFF//实际上每个进程的内核都是相同 真正能够操作的空间为 2G - 128kb
③进程的创建: 任何进程都是别的进程创建的:CreateProcess()  进程的创建过程  1、映射EXE文件  2、创建内核对象EPROCESS  3、映射系统DLL(ntdll.dll)  4、创建线程内核对象ETHREAD  5、系统启动线程(一个进程最少都有一个线程,用于执行程序)  映射DLL(ntdll.LdrlnitializeThunk)  线程开始执行
6、创建进程

进程的创建:
  1. BOOL CreateProcess(<br>    LPCTSTR IpApplicationName,              // name of executable module<br>    LPTSTR IpCommandLine,                       // command line string<br>    LPSECURITY_ATTRIBUTES IpProcessAttributes,  // SD<br>    LPSECURITY_ATTRIBUTES IpThreadAttributes,   //SD<br>    BOOL blnheritHandles,                   // handle inheritance option<br>    DWORD dwCreationFlags,                      // creation flags<br>    LPVOID IpEnvironment,                       // new environment block<br>    LPCTSTR IpCurrentDirectory,                 // current directory name<br>    LPSTARTUPINFO IpStartupInfo,                // startup information<br>    LPPROCESS_INFORMATION IpProcessInformation // process information<br>);
复制代码
//创建子进程 返回成功与失败
  1. if (!CreateProcess(<br>    szChildProcssName,  //对象名称<br>    szCommandLine,      //命令行<br>    NULL,               //不继承进程句柄<br>    NULL,               //不继承线程句柄<br>    FALSE,              //不继承句柄<br>    0,                  //没有创建标志<br>    NULL,               //使用父进程环境变量<br>    NULL,               //使用父进程目录作为当前目录,可以自己设置目录<br>    &si,                //STARTUPINFOw结构体详细信息<br>    &pi)                //PROCESS_INFORMATION结构体进程信息<br>)
复制代码
szChildProcssName 实际上是完整的路径加上 exe 的名字,
 
&si即为 指向STARTUPINFO结构的指针,该结构指定新进程的主窗口应如何显示。
&pi相当于返回值,返回一个进程和一个线程。(其中结构体的成员为 进程ID、进程句柄和线程ID、线程句柄)
7、句柄表

① 什么是内核对象?  像进程、线程、文件、互斥体、事件等在内核都有一个对应的结构体,这些结构体由内核负责管理。我们管这样的对象叫做内核对象。
②如何管理内核对象

如果我们想要操作内核对象,操作系统是无法直接将内核对象的地址暴露给用户层或者应用层的,避免出现内存访问错误。例如进程,就会提供一个句柄表,表中的数据指向内核层中的内核对象。进而起到一个防火墙的作用,不会直接的暴露地址数据。而句柄的重要性主要在于,如果没有句柄就无法进行操作内核对象。每生成一个新的内核对象,句柄表中就会多一个索引。
④多进程共享一个内核对象

存在多个进程使用同一个内核对象,而这样会在各自的句柄表中生成新的一个索引,但具体的索引值可能不尽相同。(句柄表是一个私有的概念,是私有的一张表,每一张表只对当前的进程有意义)
内核对象被一个进程使用,就会有一个句柄索引,当多个进程使用内核对象,当句柄关闭,某个进程不再使用内核对象,内核对象的进程就会减少,如果还有进程使用,就不会消亡,直到没有一个进程使用,内核对象就会消亡。(所谓的一个计数器)
而线程这个结构体不同,如果想要将线程这个结构体关闭,必须要先关闭线程(即代码执行完毕),再将内核对象的计数器置为零,两个缺一不可。(利用句柄来操作内核对象 CloseHandle,进行关闭打开的一系列操作)
⑤句柄是否“可以”被继承

其实可以具物化的想象这个句柄表实际上是三列,一列是索引值,一列是内核对象的地址,一列是句柄表示是否可以被继承的数值。
举个例子:例如 CreateEvent 这个进程
  1. HANDLE CreateEvent(<br>    LPSECURITY ATTRIBUTES lpEventAttributes, // SD<br>    BOOL hManualReset,                      // reset type<br>    BOOL bInitialstate,                     //initial state<br>    LPCTSTR IpName                          //object name<br>);
复制代码
主要是第一个参数用于判断是否继承,如果不继承就设置为 NULL , 如果是需要继承就需要创建一个结构体对象。而第一个参数是一个指向另一个结构体的指针。
  1. typedef struct _SECURITY_ATTRIBUTES {  <br>    DWORD nLength;  <br>    LPVOID lpSecurityDescriptor;  <br>    BOOL bInheritHandle;<br>} SECURITY_ATTRIBUTES,  *PSECURITY_ATTRIBUTES,  *LPSECURITY_ATTRIBUTES;
复制代码
我们想要设置句柄表能够继承的话,就需要创建一个对象。并设置初始化。
  1. SECURITY_ATTRIBUTES sa;<br>​<br>ZeroMemory(&sa,sizeof(SECURITY_ATTRIBUTES));<br>sa.nlength = sizeof(SECURITY_ATTRIBUTES);<br>sa.bInheritHandle = TRUE;<br>​<br>CreateEvent(sa,FALSE,FALSE);//所以如果想继承的话,就将这个对象传进第一个参数。
复制代码
这样的话,子进程就能继承父进程的句柄表。虽然不是完成得到,因为可能只有部分设置了可继承。但是如果子进程结构体中的成员 (不继承句柄),就不论父进程中的句柄表是否可以被继承,都不影响,子进程的句柄表。
 
⑥句柄是否“允许”被继承

于是我们就可以得到两种共享内核的解决方式,第一种就是OPEN函数来得到(同一个内核对象),第二种就是通过继承的方式。(实际上多数线程和进程都属于是内核对象,多数不继承父进程的句柄表,而当作为父进程的时候,多数将句柄表继承下去。)
8、进程相关API

① ID 与句柄

我们已经知道一个概念就是,如果我们利用 CreateProcess 函数创建了一个进程,将会给我们返回了四个数据。分别是进程编号,进程句柄,线程编号,线程句柄。句柄的一个概念是:当前进程私有的一个表中的索引(即为句柄表)。句柄都属于私有的,对于别的进程没有意义。
进程 ID 我们通常称为 PID (Process ID),句柄表这个表存储了这个进程打开了或者创建了的所有的内核对象。操作系统也有对应的一张表,称为全局句柄表,整个操作系统只有一份。其中包含了所有正在运行的进程和线程。和进程拥有的句柄表是相同的,也是包含一个索引和一个具体的地址。
进程句柄(hProcess)指的是,当前进程的句柄表所包含的索引,进程 ID(Process ID) 指的就是当前进程对应在全局句柄表中的索引。二者的区别就是进程句柄只对当前进程有意义,进程 ID 对于其他的进程也有意义。(相当于全局变量和局部变量的关系)
PID 是唯一的,一个进程(线程)对应的是一个 ID。但是有旧进程的消亡和新进程的增加,进程 ID 的特性就是唯一但并非不变。(唯一但非永远不变)
②以挂起的形式创建进程
  1. BOOL CreateProcess(<br>LPCTSTR IpApplicationName,  // name of executable module<br>LPTSTR IpCommandLine,       // command line string<br>LPSECURITY_ATTRIBUTES IpProcessAttributes,  //SD<br>LPSECURITY_ATTRIBUTES IpThreadAttributes,   //SD<br>BOOL blnheritHandles,       // handle inheritance option<br>DWORD dwCreationFlags,      // creation flags<br>LPVOID IpEnvironment,       // new environment block<br>LPCTSTR IpCurrentDirectory, // current directory name<br>LPSTARTUPINFO IpStartupInfo,// startup information<br>LPPROCESS_INFORMATION IpProcessInformation // process information<br>I
复制代码
dwCreationFlags 这个成员也有许多的值,而我们最关键的一个就是 CREATE_SUSPENDED ,即为以挂起的形式创建一个进程。
创建进程的过程分为:先有一个 exe,映射 exe文件,创建内核对象(EPROCESS),映射系统DLL(htdll.dll),创建线程内核对象 ETHREAD,系统启动线程(映射DLL,线程开始执行)。
如果我们以挂起的形式创建线程的话,进程的创建过程就会发生变化:
任何进程都是别的进程创建的:CreateProcess()  进程的创建过程  1、映射EXE文件  2、创建内核对象EPROCESS  3、映射系统DLL(ntdll.dll)  4、创建线程内核对象ETHREAD  5、系统启动线程(一个进程最少都有一个线程,用于执行程序)//如果是以挂起的系统就不会启动线程,会在恢复之后再继续执行  映射DLL(ntdll.LdrlnitializeThunk)  线程开始执行
所以我们将进程挂起的话,我们就可以在启动线程之前(即为进程启动之前),实现我们想要实现的操作。然后我们再将线程恢复,利用 ResumeThread函数即可。
③模块目录与工作目录
  1. char strModule[256];<br>GetModuleFileName(NULL,strModule, 256); //模块目录<br>​<br>char strWork[1000];<br>int i=1000;<br>GetCurrentDirectory(1000,buf);          //工作目录<br>​<br>printf("模块目录: %sIn工作目录: %s In",strModule,strWork);
复制代码
IpCurrentDirectory 这个成员,称为当前进程的工作目录。  GetModuleFileName这个 API 即指得到模块路径,你的exe在什么位置,得到的路径就是什么位置。其实较为固定的。 GetCurrentDirectory这个API 即为得到工作路径,这个路径是可以被修改的。因为这个工作路径是创建这个进程的人决定的。我们可以在 CreateProcess 中的进程目录进行自我修改,如果设置为NULL ,会自动的使用父进程目录作为当前目录。(可以理解为相对路径和绝对路径)
④其他进程相关 API:
获取进程 PID: GetCurrentProcessId 获取进程句柄: GetCurrentProcess 获取命令行: GetCommandLine 获取启动信息: GetStartupInfo 遍历进程 ID: EnumProcesses 快照 : CreateToolhelp32Snapshot(当调用这个函数,可以将当前系统中的重要信息保存下来,就可以分析当前模块、进程和线程)

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

铁佛

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表