一、什么是进程

  • 进程可以看作是一个运行中的程序,通常由一个可执行程序(.exe)所产生。一个进程最少包含了以下几个部分:

    1. - 1. 一个用于描述自己的进程内核对象。
    2. - 2. 最少一个的线程内核对象。
    3. - 3. 一个虚拟的地址空间(4GB[32位下])。
    4. - 4. 提供相应数据和代码的一系列模块。

    二、什么是模块

  • windows 下的可执行文件通常称之为模块,主要用于提供需要用到的代码和数据。在 VS 中,可以在程序断下后,通过:菜单 -> 调试 -> 窗口 -> 模块中查看到当前程序中所加载的所有模块。

    三、进程操作

  • 创建进程的基本方式: ```cpp

    include

int main() {

// 传入参数: 必须初始化,用于设置进程的启动信息
STARTUPINFOA StartupInfo{ sizeof(STARTUPINFOA) };

// 传出参数: 用于接收创建出的进程和线程的句柄以及 id
PROCESS_INFORMATION ProcessInfomation{};

// 可以使用函数 CreateWindow 通过传入的路径创建一个进程
BOOL Result = CreateProcessA(
    "C:\\Windows\\System32\\notepad.exe",        // 指定用于创建进程的可执行文件
    NULL,                                        // 命令行参数,如果不写可以为 NULL
    NULL,                                        // 表示为进程使用默认的安全属性
    NULL,                                        // 表示为进程中主线程使用的安全属性
    FALSE,                                        // 是否需要继承父进程的可继承对象
    NULL,                                        // 创建进程的标志位: 使用新控制台\调试
    NULL,                                        // 使用到的环境变量,NULL 表示使用默认的
    NULL,                                        // 设置当前的工作路径,供相对路径参考
    &StartupInfo,                                // 提供进程的启动信息
    &ProcessInfomation);                        // 接收进程和线程句柄以及相应的 id

// 如果进程创建成功,会返回新的进程和线程的句柄,为了防止句柄泄露,
//    应该使用 CloseHandle 来关闭句柄
if (Result != FALSE)
{
    CloseHandle(ProcessInfomation.hThread);
    CloseHandle(ProcessInfomation.hProcess);
}

return 0;

}


   - 进程的操作
```cpp
#include <windows.h>

int main()
{
    // 1. 可以使用 FindWindow 函数来查找到窗口句柄
    HWND hWnd = FindWindow(NULL, L"无标题 - 记事本");

    // 2. 通过函数 GetWindowThreadProcessId 可以找到对应窗口的 PID
    DWORD Pid = 0;
    GetWindowThreadProcessId(hWnd, &Pid);

    // 3. 使用获取到的进程 ID 以指定的权限打开目标进程
    //    3.1 表示当前需要一个拥有什么权限的内核对象句柄
    //    3.2 表示当前的句柄是否是一个可继承句柄,需要配合继承
    //    3.3 一个 PID 表示需要打开的是哪一个进程内核对象
    HANDLE Process = OpenProcess(PROCESS_TERMINATE, FALSE, Pid);

    // 4. 传入目标进程句柄,执行相应的操作,例如关闭它
    TerminateProcess(Process, -1);

    // 5. 操作完成后为了避免句柄泄露,需要关闭内核对象句柄
    CloseHandle(Process);

    // 6. 有的时候,也可以使用这个函数来结束当前的进程
    ExitProcess(-1);


    return 0;
}
  • 进程的遍历 ```cpp

    include

    include

    include

int main() { // 1. 拍摄一个进程快照,保存的是调用函数的这一刻系统内的进程情况,第二个参数 // 没有意义 HANDLE Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

// 2. 创建 PROCESSENTRY32 用于保存遍历到的进程的信息
PROCESSENTRY32 ProcessInfo{ sizeof(PROCESSENTRY32) };

// 3. 通过 Process32First 查看快照内的第一个进程的信息
if (TRUE == Process32First(Snapshot, &ProcessInfo))
{
    do {
        // 4. 输出进程快照给我们提供的一系列信息
        printf("%08X[%08X](%d): %S\n", 
            ProcessInfo.th32ProcessID,                    // 进程ID
            ProcessInfo.th32ParentProcessID,            // 父进程ID
            ProcessInfo.cntThreads,                        // 线程ID
            ProcessInfo.szExeFile);                        // 进程名称

        // 通过下面的函数可以找到指定进程对应模块的的全路径
        DWORD Size{ MAX_PATH };
        WCHAR Path[MAX_PATH]{};
        HANDLE Process = OpenProcess(PROCESS_QUERY_INFORMATION, 
                            FALSE, 
                            ProcessInfo.th32ProcessID);
        QueryFullProcessImageName(Process, 0, Path, &Size);
        printf("\t%S\n", Path);
        CloseHandle(Process);

        // 5. 尝试继续读取到快照中的下一个进程信息
    } while (Process32Next(Snapshot, &ProcessInfo));
}


CloseHandle(Snapshot);
return 0;

}

进程是操作系统管理的,遍历的时候,能够遍历出系统中的所有进程的信息:进程名,路径,进程ID<br />遍历进程的用处:通常来说我们都是知道进程名,然后去找到ID(ID每一次程序运行的时候都是不一样的),我们如果要操作进程,就需要使用OpenProcess函数得到它的句柄,OpenProcess这个函数,就是根据进程ID得到句柄的。

   - 模块的遍历
```cpp
#include <iostream>
#include <Windows.h>
#include <Tlhelp32.h>

int main()
{
    // 1. 拍摄一个模块快照,保存的是调用函数的这一刻系统内的进程情况,第二个参数是进程id
    HANDLE Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 18388);

    // 2. 创建 MODULEENTRY32 用于保存遍历到的模块的信息
    MODULEENTRY32 ModuleInfo{ sizeof(MODULEENTRY32) };

    // 3. 通过 Module32First 查看快照内的第一个模块的信息
    if (TRUE == Module32First(Snapshot, &ModuleInfo))
    {
        do {
            // 4. 输出进程快照给我们提供的一系列信息
            printf("模块名称[%08X]: %S\n", ModuleInfo.th32ProcessID, ModuleInfo.szModule);
            printf("模块句柄: %p\n", ModuleInfo.hModule);
            printf("加载基址: %p\n", ModuleInfo.modBaseAddr);
            printf("模块大小: %d\n", ModuleInfo.modBaseSize);
            printf("模块路径: %S\n\n", ModuleInfo.szExePath);


            // 5. 尝试继续读取到快照中的下一个进程信息
        } while (Module32Next(Snapshot, &ModuleInfo));
    }


    CloseHandle(Snapshot);
    return 0;
}