终止进程

终止进程会导致以下情况:

  • 进程打开的所有对象句柄均已关闭。
  • 进程中的所有线程均终止其执行。
  • 进程对象的状态被发出信号,满足了一直在等待进程终止的所有线程。
  • 进程中所有线程的状态都将发出信号,满足所有一直在等待线程终止的线程。
  • 流程的终止状态从STILL_ACTIVE更改为流程的退出值。

    ExitProcess

    终止当前进程及其所有线程。
    1. VOID ExitProcess(
    2. UINT uExitCode // exit code for all threads
    3. );
    ExitProcess是结束进程的首选方法。
    此功能提供了干净的进程关闭。
    这包括调用所有附加的动态链接库(DLL)的入口点函数,该值指示该进程正在从DLL分离。
    如果某个进程通过调用TerminateProcess终止,则不会通知该进程所连接的DLL进程终止。
    所有附加的DLL执行完任何进程终止值后,此函数将终止当前进程

    TerminateProcess

    终止指定的进程及其所有线程。
    1. BOOL TerminateProcess(
    2. HANDLE hProcess, // 进程句柄,句柄必须具有PROCESS_TERMINATE访问权限。
    3. UINT uExitCode // 指定该进程以及由于此调用而终止的所有线程的退出码。
    4. // 使用GetExitCodeProcess函数检索进程的退出值。
    5. // 使用GetExitCodeThread函数检索线程的退出值
    6. );
    TerminateProcess函数用于无条件地导致进程退出。仅在极端情况下使用。
    如果使用TerminateProcess而不是ExitProcess,则可能损害由动态链接库(DLL)维护的全局数据的状态。
    TerminateProcess导致进程中的所有线程终止,并导致进程退出,但未通知该进程所连接的DLL正在终止。
    调用示例:
    1. DWORD dwPid = 0;
    2. GetWindowThreadProcessId(hWnd, &dwPid);
    3. HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
    4. TerminateProcess(hProcess, -1);

获取进程模块名

GetModuleBaseName

  1. DWORD GetModuleBaseName(
  2. HANDLE hProcess, // 进程句柄
  3. HMODULE hModule, // 模块句柄
  4. LPTSTR lpBaseName, // 接收基名称的缓冲区
  5. DWORD nSize // 缓冲区大小
  6. );

获取进程id(pid), 线程id(tid)

GetCurrentProcessId

返回当前进程的pid。无参数

  1. DWORD GetCurrentProcessId();

GetWindowThreadProcessId

获取创建指定窗口的tid和pid

  1. DWORD dwPid = 0;
  2. DWORD ndThreadId = GetWindowThreadProcessId(hwnd, &dwPid);
  1. tid, pid = GetWindowThreadProcessId(hwnd)

获取进程句柄(hProcess)

GetCurrentProcess

返回当前进程的句柄
注: 其实当前进程句柄直接用(HANDLE)-1这个伪句柄即可, 代表是当前进程句柄. 没必要调用这个函数

OpenProcess

OpenProcess根据指定的pid获取hProcess,打开一个已存在的进程对象,并返回进程的句柄。

  1. HANDLE OpenProcess(
  2. DWORD dwDesiredAccess; // 想得到的访问权限,一般是 PROCESS_ALL_ACCESS 等
  3. BOOL bInheritHandle; // 指定返回的句柄是否可以被继承
  4. DWORD dwProcessId; // 指定要打开的进程的 PID 等
  5. );
  1. hProcess = OpenProcess(reqdAccess, bInherit , pid )

返回值:

  • 如果函数成功,则返回值是指定进程的进程句柄hProcess。
  • 如果函数失败,则返回值为NULL。

调用示例:
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwpid);
参数:

  • dwDesiredAccess: 对于支持安全检查的操作系统,将针对目标进程的任何安全描述符检查此访问。

除STANDARD_RIGHTS_REQUIRED访问标志外,还可以指定以下访问标志的任意组合:

  • PROCESS_ALL_ACCESS 指定进程对象的所有可能访问标志。
  • PROCESS_CREATE_PROCESS 在内部使用。
  • PROCESS_CREATE_THREAD 允许使用CreateRemoteThread函数中的进程句柄在进程中创建线程。
  • PROCESS_DUP_HANDLE 允许使用进程句柄作为DuplicateHandle函数中的源进程或目标进程来复制句柄。
  • PROCESS_QUERY_INFORMATION 允许使用GetExitCodeProcess和GetPriorityClass函数中的进程句柄从进程对象中读取信息。
  • PROCESS_SET_INFORMATION 允许使用SetPriorityClass函数中的进程句柄来设置进程的优先级。
  • PROCESS_TERMINATE 允许使用TerminateProcess函数中的进程句柄终止进程。
  • PROCESS_VM_OPERATION 允许使用VirtualProtectEx和WriteProcessMemory函数中的进程句柄来修改进程的虚拟内存。
  • PROCESS_VM_READ 允许使用ReadProcessMemory函数中的进程句柄从进程的虚拟内存中读取。
  • PROCESS_VM_WRITE 允许使用WriteProcessMemory函数中的进程句柄写入进程的虚拟内存。
  • SYNCHRONIZE Windows NT:允许在任何等待函数中使用进程句柄等待进程终止。
    • bInheritHandle: 指定返回的句柄是否可以由当前进程创建的新进程继承。如果为TRUE,则句柄是可继承的。
    • dwProcessId: 指定要打开的进程的进程标识符。

枚举指定进程的模块

EnumProcessModules

枚举指定进程的模块

  1. BOOL EnumProcessModules(
  2. HANDLE hProcess, // 进程句柄
  3. HMODULE * lphModule, // 接收模块句柄的数组
  4. DWORD cb, // 数组大小
  5. LPDWORD lpcbNeeded // 接收返回的字节数
  6. );

写进程内存

WriteProcessMemory

在指定的进程中写入内存。要写入的整个区域必须是可访问的,否则操作将失败。

  1. BOOL WriteProcessMemory(
  2. HANDLE hProcess, // 内存被写入的进程的句柄
  3. LPVOID lpBaseAddress, // 开始写的地址
  4. LPVOID lpBuffer, // 存放要写入的数据的缓冲区地址
  5. DWORD nSize, // 要写入的字节数
  6. LPDWORD lpNumberOfBytesWritten // 实际写入到缓冲区的字节数的指针。如果为空,则忽略该参数。
  7. );

调用示例:

  1. DWORD dwDllBase = (DWORD)GetModuleHandleA(DmDLLNAME);
  2. byte buf[1] = {1};
  3. WriteProcessMemory((HANDLE)-1, (void*)(dwDllBase + 1078240), buf, 1, NULL);

读进程内存

ReadProcessMemory

读取指定进程中的内存。要读取的整个区域必须是可访问的,否则操作将失败。

  1. BOOL ReadProcessMemory(
  2. HANDLE hProcess, // 读取内存的进程的句柄
  3. LPCVOID lpBaseAddress, // 开始读的地址
  4. LPVOID lpBuffer, // 存放读取数据的缓冲区地址
  5. DWORD nSize, // 要读取的字节数
  6. LPDWORD lpNumberOfBytesRead // 实际读取到缓冲区的字节数的指针。如果为空,则忽略该参数。
  7. );