进程相关API

ID与句柄

如果我们成功创建一个进程,CreateProcess函数会给我们返回一个结构体,包括四个数
据:进程编号(ID)、进程句柄、线程编号(ID)、线程句柄.

进程ID其实我们早见过了,通常我们称之为PID


句柄每一个进程都有一张自己的私有的表,而操作系统也有一份句柄表,我们称为全局句柄表,这张表存储着私有的内核对象.
系统句柄表

PID我们就可以理解为全局句柄表中的一个索引,那么PID和句柄的区别就很容易看出来了,PID是全局的,在任何进程中都有意义,都可以使用,而句柄则是句柄的、私有的;PID是唯一的,绝对不可能出现重复的存在,但是当进程消失,那么这个PID就有可能会分给另一个进程。(PID不是句柄,但是可以通过PID获取得到全局句柄表中对应的句柄)

TerminateProcess函数

BOOL TerminateProcess(
HANDLE hProcess, // handle to the process 句柄
UINT uExitCode // exit code for the process 退出代码
;

1.创建一个进程A

2.使用B进程来结束A

TerminateProcess函数是用来终止进程的,具体的可以参考MSDN Library,在这里我们很清楚的可以看见终止
进程失败了,这个错误编号的意思就是句柄无效,那么就论证了句柄是私有的,其他进程无法根据这个句柄来
终止进程,但是我们想要真正的关闭这个进程,那就需要借助PID来获取句柄了,具体细节如下。

openProcess

Opens an existing local process object.
HANDLE WINAPI OpenProcess(
  DWORD dwDesiredAccess,//打开进程的的权限问题 access flag 你希望的访问权限
  BOOL bInheritHandle,//允不允许子进程继承呢
  DWORD dwProcessId  //全局PID  进程ID
);

我通过PID打开进程(OpenProcess函数),拥有所有权,不继承句柄表当前OpenProess函数执行完之后,我就获得一个句柄,通过这个句柄我就可以终止进程

HANDLE hProcess;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 0x524);
if(!TerminateProcess(hProcess, 0)) {
printf("终止进程失败:%d \n", GetLastError());
}

以挂起的形式创建进程

Creates a new process and its primary thread. The new process runs in the security context of the calling process.
创建一个新进程和它的主要线程。这个新进程跑再一个安全正在调用的进程上下文中
第六个参数DWORD dwCreationFlags

BOOL WINAPI CreateProcess(
  LPCTSTR lpApplicationName,
  LPTSTR lpCommandLine,
  LPSECURITY_ATTRIBUTES lpProcessAttributes,
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  BOOL bInheritHandles,
  DWORD dwCreationFlags,//创建一个新的控制台
  LPVOID lpEnvironment,
  LPCTSTR lpCurrentDirectory,
  LPSTARTUPINFO lpStartupInfo,
  LPPROCESS_INFORMATION lpProcessInformation
);

当我们创建一个控制台进程时,会发现子进程和父进程都在都一个命令控制台中
而如果我们想要区分的话就需要借助dwCreationFlags这个参数,将其修改为CREATE_NEW_CONSOLE即可:但是这个并不是我们最重要的,或者说不是其真正有意义的参数,有意义的事参数值为CREATE_SUSPEND,也就是以挂起的形式创建进程。

回顾

1.进程的创建

我们需要知道任何进程都是别的进程创建的,当我们在Windows下双击一个文件,实际上就是explore.exe这个进程创建我们打开文件的进程,其使用的方法就是:CreateProcess()

  1. 任何进程都是别的进程创建的:CreateProcess()

  2. 进程创建过程

1.映射EXE文件 (低2G)

2.创建内核对象EPROCESS (高2G)

3.映射系统DLL (ntdll.dll)

4.创建线程内核对象RTHREAD(高2G)

5.系统启动线程
映射DLL(ntdll.KdrInitialize Thunk)
线程开始执行

2.进程的创建

1.映射EXE文件
2.创建内核对象EPROCESS
3.映射系统DLL(ntdll.dll)
4.创建线程内核对象ETHREAD
5.如果是挂起的方式创建的:
.....
6.恢复以后再继续执行
1.映射DLL(ntdll.KdrInitializeThunk)

  2.线程开始执行

那也就说明了一点,挂起本质上挂起的是线程,进程还是会创建的,所以,最终如果想恢复的话也是恢复线程

模块与工作目录

GetModuleFileNameGetCurrentDirectory函数可以分别获得当前模块目录和当前工作目录:
char strModule[256];
GetModuleFileName(NULL,strModule,256);//得到当前模块目录,当前exe所在的路径,包含exe文件名
char strWork[1000];
int i = 1000;
GetCurrentDirectory(1000,buf);//获取当前工作目录
printf("某块目录:%s\n 工作目录:%s\n",strModule,strWork);

GetModuleFileName

获取当前模块的路径

获取现有目录

GetCurrentDirectory需要注意的是工作目录是可以修改的,我们可以通过CreateProcess函数来创建一个进程,并且修改其工作目录,这是CreateProcess函数的第8个参数LPCTSTR lpCurrentDirectory.

其他相关API

  • 获取进程PID
    GetCurrentProcessId
  • 获取进程句柄
    GetCurrentProcess
  • 获取命令行
    GetCommandLine
  • 获取启动信息
    GetStartupinfo
  • 遍历进程ID
    EnumProcesses
  • 快照
    CreateToolhelp32napshot
posted @ 2022-04-04 17:59  不会笑的孩子  阅读(198)  评论(0编辑  收藏  举报