首页 > 其他分享 >Win32 2

Win32 2

时间:2023-07-15 21:33:07浏览次数:25  
标签:对象 句柄 Win32 线程 内核 创建 进程

5、进程

进程是指运行中的一个程序。(X)

①什么是进程? 进程提供程序所需的资源,如:数据、代码等等。

程序运行起的状态与进程没有关系,举个例子,程序就相当于一个房子,进程就是其中的东西,而使用这些房子中的东西的人称为线程。

②进程内存空间的地址划分

分区 x86 32位Windows 空指针赋值区 0x00000000 -0x0000FFFF //操作系统都没有使用的空间 用户模式区 0x00010000-0x7FFEFFFF 64KB禁入区 0x7FFF0000-0x7FFFFFFF 内核 0x80000000-0xFFFFFFFF//实际上每个进程的内核都是相同 真正能够操作的空间为 2G - 128kb

③进程的创建: <1>任何进程都是别的进程创建的:CreateProcess() <2> 进程的创建过程 1、映射EXE文件 2、创建内核对象EPROCESS 3、映射系统DLL(ntdll.dll) 4、创建线程内核对象ETHREAD 5、系统启动线程(一个进程最少都有一个线程,用于执行程序) 映射DLL(ntdll.LdrlnitializeThunk) 线程开始执行

6、创建进程

进程的创建:

BOOL CreateProcess(
LPCTSTR IpApplicationName, // name of executable module
LPTSTR IpCommandLine, // command line string
LPSECURITY_ATTRIBUTES IpProcessAttributes, // SD
LPSECURITY_ATTRIBUTES IpThreadAttributes, //SD
BOOL blnheritHandles, // handle inheritance option
DWORD dwCreationFlags, // creation flags
LPVOID IpEnvironment, // new environment block
LPCTSTR IpCurrentDirectory, // current directory name
LPSTARTUPINFO IpStartupInfo, // startup information
LPPROCESS_INFORMATION IpProcessInformation // process information
);

//创建子进程 返回成功与失败

if (!CreateProcess(
szChildProcssName, //对象名称
szCommandLine, //命令行
NULL, //不继承进程句柄
NULL, //不继承线程句柄
FALSE, //不继承句柄
0, //没有创建标志
NULL, //使用父进程环境变量
NULL, //使用父进程目录作为当前目录,可以自己设置目录
&si, //STARTUPINFOw结构体详细信息
&pi) //PROCESS_INFORMATION结构体进程信息
)

szChildProcssName 实际上是完整的路径加上 exe 的名字,

 

&si即为 指向STARTUPINFO结构的指针,该结构指定新进程的主窗口应如何显示。

&pi相当于返回值,返回一个进程和一个线程。(其中结构体的成员为 进程ID、进程句柄和线程ID、线程句柄)

7、句柄表

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

②如何管理内核对象

image-20230122105704715

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

④多进程共享一个内核对象

image-20230122110336845

存在多个进程使用同一个内核对象,而这样会在各自的句柄表中生成新的一个索引,但具体的索引值可能不尽相同。(句柄表是一个私有的概念,是私有的一张表,每一张表只对当前的进程有意义)

内核对象被一个进程使用,就会有一个句柄索引,当多个进程使用内核对象,当句柄关闭,某个进程不再使用内核对象,内核对象的进程就会减少,如果还有进程使用,就不会消亡,直到没有一个进程使用,内核对象就会消亡。(所谓的一个计数器)

而线程这个结构体不同,如果想要将线程这个结构体关闭,必须要先关闭线程(即代码执行完毕),再将内核对象的计数器置为零,两个缺一不可。(利用句柄来操作内核对象 CloseHandle,进行关闭打开的一系列操作)

⑤句柄是否“可以”被继承

image-20230122111748876

其实可以具物化的想象这个句柄表实际上是三列,一列是索引值,一列是内核对象的地址,一列是句柄表示是否可以被继承的数值。

举个例子:例如 CreateEvent 这个进程

HANDLE CreateEvent(
LPSECURITY ATTRIBUTES lpEventAttributes, // SD
BOOL hManualReset, // reset type
BOOL bInitialstate, //initial state
LPCTSTR IpName //object name
);

主要是第一个参数用于判断是否继承,如果不继承就设置为 NULL , 如果是需要继承就需要创建一个结构体对象。而第一个参数是一个指向另一个结构体的指针。

typedef struct _SECURITY_ATTRIBUTES {  
DWORD nLength;  
LPVOID lpSecurityDescriptor;  
BOOL bInheritHandle;
} SECURITY_ATTRIBUTES,  *PSECURITY_ATTRIBUTES,  *LPSECURITY_ATTRIBUTES;

我们想要设置句柄表能够继承的话,就需要创建一个对象。并设置初始化。

SECURITY_ATTRIBUTES sa;

ZeroMemory(&sa,sizeof(SECURITY_ATTRIBUTES));
sa.nlength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;

CreateEvent(sa,FALSE,FALSE);//所以如果想继承的话,就将这个对象传进第一个参数。

这样的话,子进程就能继承父进程的句柄表。虽然不是完成得到,因为可能只有部分设置了可继承。但是如果子进程结构体中的成员 (不继承句柄),就不论父进程中的句柄表是否可以被继承,都不影响,子进程的句柄表。

 

⑥句柄是否“允许”被继承

image-20230122200225211

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

8、进程相关API

① ID 与句柄

image-20230122202801420

我们已经知道一个概念就是,如果我们利用 CreateProcess 函数创建了一个进程,将会给我们返回了四个数据。分别是进程编号,进程句柄,线程编号,线程句柄。句柄的一个概念是:当前进程私有的一个表中的索引(即为句柄表)。句柄都属于私有的,对于别的进程没有意义。

进程 ID 我们通常称为 PID (Process ID),句柄表这个表存储了这个进程打开了或者创建了的所有的内核对象。操作系统也有对应的一张表,称为全局句柄表,整个操作系统只有一份。其中包含了所有正在运行的进程和线程。和进程拥有的句柄表是相同的,也是包含一个索引和一个具体的地址。

进程句柄(hProcess)指的是,当前进程的句柄表所包含的索引,进程 ID(Process ID) 指的就是当前进程对应在全局句柄表中的索引。二者的区别就是进程句柄只对当前进程有意义,进程 ID 对于其他的进程也有意义。(相当于全局变量和局部变量的关系)

PID 是唯一的,一个进程(线程)对应的是一个 ID。但是有旧进程的消亡和新进程的增加,进程 ID 的特性就是唯一但并非不变。(唯一但非永远不变)

②以挂起的形式创建进程

BOOL CreateProcess(
LPCTSTR IpApplicationName, // name of executable module
LPTSTR IpCommandLine, // command line string
LPSECURITY_ATTRIBUTES IpProcessAttributes, //SD
LPSECURITY_ATTRIBUTES IpThreadAttributes, //SD
BOOL blnheritHandles, // handle inheritance option
DWORD dwCreationFlags, // creation flags
LPVOID IpEnvironment, // new environment block
LPCTSTR IpCurrentDirectory, // current directory name
LPSTARTUPINFO IpStartupInfo,// startup information
LPPROCESS_INFORMATION IpProcessInformation // process information
I

dwCreationFlags 这个成员也有许多的值,而我们最关键的一个就是 CREATE_SUSPENDED ,即为以挂起的形式创建一个进程。

创建进程的过程分为:先有一个 exe,映射 exe文件,创建内核对象(EPROCESS),映射系统DLL(htdll.dll),创建线程内核对象 ETHREAD,系统启动线程(映射DLL,线程开始执行)。

如果我们以挂起的形式创建线程的话,进程的创建过程就会发生变化:

<1>任何进程都是别的进程创建的:CreateProcess() <2> 进程的创建过程 1、映射EXE文件 2、创建内核对象EPROCESS 3、映射系统DLL(ntdll.dll) 4、创建线程内核对象ETHREAD 5、系统启动线程(一个进程最少都有一个线程,用于执行程序)//如果是以挂起的系统就不会启动线程,会在恢复之后再继续执行 映射DLL(ntdll.LdrlnitializeThunk) 线程开始执行

所以我们将进程挂起的话,我们就可以在启动线程之前(即为进程启动之前),实现我们想要实现的操作。然后我们再将线程恢复,利用 ResumeThread函数即可。

③模块目录与工作目录

char strModule[256];
GetModuleFileName(NULL,strModule, 256); //模块目录

char strWork[1000];
int i=1000;
GetCurrentDirectory(1000,buf); //工作目录

printf("模块目录: %sIn工作目录: %s In",strModule,strWork);

IpCurrentDirectory 这个成员,称为当前进程的工作目录。 GetModuleFileName这个 API 即指得到模块路径,你的exe在什么位置,得到的路径就是什么位置。其实较为固定的。 GetCurrentDirectory这个API 即为得到工作路径,这个路径是可以被修改的。因为这个工作路径是创建这个进程的人决定的。我们可以在 CreateProcess 中的进程目录进行自我修改,如果设置为NULL ,会自动的使用父进程目录作为当前目录。(可以理解为相对路径和绝对路径)

④其他进程相关 API:

获取进程 PID: GetCurrentProcessId 获取进程句柄: GetCurrentProcess 获取命令行: GetCommandLine 获取启动信息: GetStartupInfo 遍历进程 ID: EnumProcesses 快照 : CreateToolhelp32Snapshot(当调用这个函数,可以将当前系统中的重要信息保存下来,就可以分析当前模块、进程和线程)

标签:对象,句柄,Win32,线程,内核,创建,进程
From: https://www.cnblogs.com/cyxyrq-code-loading/p/17556997.html

相关文章

  • 基于DirectX11+ImGui的Win32桌面程序开发
    一、常见图形界面框架(DirectUI、GUI)1.题外话,纯属扯O举两个常用的开发框架,MFC和QtWidget里面每个控件都是Window,这是和DirectUI最大的区别。下面简单梳理下这个DirectUI与GUI之前错综复杂的爱恨情仇:1.在侏罗纪时期,传统的Handle式GUI框架,是由操作系统内核(win32k.sys)直......
  • 记录一个boost1.72和Win32api的冲突
    报错:2>C:\ProgramFiles(x86)\WindowsKits\10\Include\10.0.19041.0\um\fileapi.h(53,1):errorC2116:'boost::interprocess::winapi::CreateDirectoryA':functionparameterlistsdonotmatchbetweendeclarations2>D:\software\boost_1_7......
  • C# WinForm开发,使用dnSpy-net-win32调试dll文件或.exe文件工具
     工具下载:https://download.csdn.net/download/haojuntu/87967457打开文件,加载需要调试文件 视图-》窗口-》模块断点,可以调试具体模块 找到要调试的模块,启动项目后,类似vs开发,可以一步步调试 ......
  • win32k.sys 是 Windows 操作系统中的一个系统文件,它是负责管理图形操作、窗口绘制和用
    win32k.sys是Windows操作系统中的一个系统文件,它是负责管理图形操作、窗口绘制和用户界面的部分。这个文件位于C:\Windows\System32\drivers\文件夹中。win32k.sys文件是一个核心的系统文件,它在系统启动时加载到内存中,并为应用程序提供图形和窗口管理的支持。它通过与硬件......
  • Win32k 是 Windows 操作系统中的一个核心组件,它负责处理图形显示、窗口管理和用户交互
    Win32k是Windows操作系统中的一个核心组件,它负责处理图形显示、窗口管理和用户交互等功能。在Windows中,Win32k.sys是一个内核模式驱动程序,它提供了访问图形子系统的接口。因此,Win32k具有较高的权限和特权。作为一个内核模式驱动程序,Win32k有比普通用户程序更高的权限级别......
  • 程序删除自身 c++ win32
    include<windows.h>//设置本程序进程基本为实时执行,快速退出。SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS);SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL);//通知资源管理器,本程序删除SHChangeNotify(SHCNE_DELETE,SHCNF_PA......
  • Python+pywin32批量转换Word文件为PDF文件
    代码功能:把当前文件夹中多个Word文件批量转换为PDF文件技术原理:代码实际上是调用了Word的“导出”功能,模拟了手工转换的操作并实现了自动化,要求已正确安装Python扩展库pywin32和Office2007以上版本。......
  • Python+pywin32操作Excel文件常用功能(268行代码+注释)
    问题描述:使用Python扩展库pywin32操作Excel文件。准备工作:安装Python,安装扩展库pywin32,安装Office或WPS。参考代码:运行结果:公众号“Python小屋”......
  • win32基础界面开发
    项目创建在VS2022中选择空项目,点击下一步,输入相关信息后点击创建。用鼠标右键点击右边解决方案下的项目名字,打开属性页,将配置改为所有配置,平台改为所有平台。接着找到配置属性中的链接器中的系统,将子系统从控制台(/SUBSYSTEM:CONSOLE)改成窗口(/SUBSYSTEM:WINDOWS),点击确定。......
  • python运行使用pywin32下载及安装问题
     1、python执行报错File"F:\XXX\XXX.py",line7,in<module> 运行python程序,提示错误如下:importwin32gui ModuleNotFoundError:Nomodulenamed'win32gui'该报错信息表示在F:\XXX\XXX.py中的第7行引入了win32gui,但是当前设备缺少pywin32的模块,需要安装安装方式一:直......