简言:
在此之前,我们发现有的WindowsAPI函数调用,必须传入相关的句柄
比如通过Findwindow获取窗口句柄,这个窗口句柄就成为了另外的API函数调用的重要的参数
这就足以说明句柄的重要地位。
简单来说,当获取到了窗口句柄之后,也就拿到操作它的权限
之后就可以把句柄传给任何别的函数,让这些函数操作。好像一张通行证,拿到它,就可以在编程之路上畅通无阻。
而窗口有窗口的句柄。
进程也有进程的句柄。
OpenProcess函数:
拿到进程句柄,就相当于拿到了进程操作的权限
然后就可以把这个句柄传给其他的进程操作函数调用
语法:
HANDLE OpenProcess(DWORD dwDesiredAccess, // 访问权限BOOL bInheritHandle, // 是否允许子进程继承句柄DWORD dwProcessId // 进程 ID
);
参数:
[in] dwDesiredAccess:
- 对进程对象的访问。 针对进程的安全描述符检查此访问权限。 此参数可以是一个或多个 进程访问权限。
- 其中有很多的访问权限,那么我们应该选择哪个呢?
没错,选择我们的PROCESS_ALL_ACCESS
[in] bInheritHandle
- 如果此值为 TRUE,则此进程创建的进程将继承句柄。 否则,进程不会继承此句柄。
[in] dwProcessId
- 目标进程的 ID。你可以通过
GetProcessId
或其他方法获得进程 ID。
返回值
- 成功时,返回目标进程的句柄(
HANDLE
类型)。该句柄可用于进一步的进程操作。 - 失败时,返回
NULL
。可以通过调用GetLastError
获取错误代码,通常是ERROR_ACCESS_DENIED
(权限不足)或者ERROR_INVALID_PARAMETER
(无效的进程 ID)。
代码实例:
我打开了一个软件:植物大战僵尸,先获取窗口id(PID),我们看看对不对:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <wchar.h> // 需要引入宽字符库
#include <locale.h> // 需要包含 locale.h 头文件
#include <windows.h>//window api函数
#include <tchar.h>#pragma comment(lib, "urlmon.lib") int main()
{//获取idHWND hWnd = FindWindowA(NULL,"植物大战僵尸中文版");printf("%x\n",hWnd);DWORD ProcessId = 0; // 使用 DWORD 类型GetWindowThreadProcessId(hWnd, &ProcessId);printf("pid=%d\n",ProcessId);HANDLE ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);getchar();return 1;
}
输出:
操作
我们现在获取了进程句柄,接下来就可以进行一系列的操作,比如说,读取进程的内存
ReadProcessMemory函数
- 用途:从目标进程的地址空间中读取数据。
- 语法:
BOOL ReadProcessMemory(HANDLE hProcess, // 目标进程的句柄LPCVOID lpBaseAddress, // 要读取的内存的起始地址LPVOID lpBuffer, // 存储读取数据的缓冲区SIZE_T nSize, // 要读取的字节数SIZE_T* lpNumberOfBytesRead // 实际读取的字节数 );
我们先了解,下一章再见