kernel32.dll核心函数详细使用示例重点讲解
每个函数的参数构建方法(包括参数含义、取值规则、构建逻辑
一、进程管理类函数
1. CreateProcessW - 创建新进程(启动外部程序)
作用说明
创建一个新进程和主线程,可启动外部可执行文件(如记事本、浏览器),是Windows启动进程的核心函数。
参数构建(共10个参数,核心参数标注★)
| 参数名 | 类型 | 含义与构建规则 |
|---|---|---|
| lpApplicationName★ | LPCWSTR | 要启动的程序路径(如L"notepad.exe"),NULL则从lpCommandLine提取 |
| lpCommandLine | LPWSTR | 命令行参数(如L"notepad.exe test.txt"),优先级高于lpApplicationName |
| lpProcessAttributes | LPSECURITY_ATTRIBUTES | 进程安全属性,NULL表示默认(不可继承) |
| lpThreadAttributes | LPSECURITY_ATTRIBUTES | 线程安全属性,NULL表示默认(不可继承) |
| bInheritHandles | BOOL | 是否继承父进程句柄,FALSE=不继承(推荐) |
| dwCreationFlags | DWORD | 创建标志:0=默认,CREATE_NEW_CONSOLE=新建控制台,CREATE_NO_WINDOW=无窗口 |
| lpEnvironment | LPVOID | 环境变量,NULL=继承父进程环境变量 |
| lpCurrentDirectory | LPCWSTR | 进程当前工作目录,NULL=父进程工作目录 |
| lpStartupInfo★ | LPSTARTUPINFOW | 进程启动信息(窗口位置、显示方式等),需初始化结构体大小 |
| lpProcessInformation★ | LPPROCESS_INFORMATION | 输出参数,返回进程/线程句柄、PID/TID,需初始化 |
完整示例(启动记事本并打开test.txt)
cpp
#include <windows.h>
#include <iostream>
#pragma comment(lib, "kernel32.lib")
int main() {
// 1. 构建STARTUPINFOW结构体(必须初始化cb大小)
STARTUPINFOW si = {0};
si.cb = sizeof(STARTUPINFOW); // 核心:设置结构体大小
si.dwFlags = STARTF_USESHOWWINDOW; // 使用wShowWindow参数
si.wShowWindow = SW_SHOW; // 窗口显示方式:正常显示
// 2. 构建PROCESS_INFORMATION结构体(输出进程/线程信息)
PROCESS_INFORMATION pi = {0};
// 3. 调用CreateProcessW启动进程
BOOL bRet = CreateProcessW(
L"notepad.exe", // 要启动的程序
L"notepad.exe test.txt", // 命令行参数(打开test.txt)
NULL, // 进程安全属性(默认)
NULL, // 线程安全属性(默认)
FALSE, // 不继承句柄
0, // 默认创建标志
NULL, // 继承父进程环境变量
NULL, // 继承父进程工作目录
&si, // 启动信息
&pi // 输出进程信息
);
// 4. 错误处理与结果输出
if (bRet) {
std::cout << "进程创建成功!" << std::endl;
std::cout << "进程PID:" << pi.dwProcessId << std::endl;
std::cout << "线程TID:" << pi.dwThreadId << std::endl;
// 5. 等待进程退出(可选)
WaitForSingleObject(pi.hProcess, 5000); // 等待5秒
// 6. 释放句柄(必须!否则资源泄漏)
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
} else {
std::cout << "进程创建失败,错误码:" << GetLastError() << std::endl;
}
return 0;
}
注意事项
- 若
lpApplicationName为NULL,lpCommandLine必须以可执行文件路径开头(如L"notepad.exe"); STARTUPINFOW的cb成员必须初始化,否则函数调用失败;- 进程/线程句柄使用后必须用
CloseHandle释放。
2. OpenProcess - 打开已有进程(获取操作权限)
作用说明
根据进程ID(PID)打开指定进程,获取进程句柄,用于后续的内存读写、进程控制等操作。
参数构建(共3个参数)
| 参数名 | 类型 | 含义与构建规则 |
|---|---|---|
| dwDesiredAccess★ | DWORD | 期望的访问权限:PROCESS_ALL_ACCESS=所有权限(需管理员),PROCESS_VM_READ=只读内存,PROCESS_VM_WRITE=写内存 |
| bInheritHandle | BOOL | 句柄是否可继承,FALSE=不可继承(推荐) |
| dwProcessId★ | DWORD | 目标进程的PID(可通过任务管理器、CreateProcessW、EnumProcesses获取) |
完整示例(打开记事本进程并获取句柄)
cpp
#include <windows.h>
#include <iostream>
#pragma comment(lib, "kernel32.lib")
int main() {
// 1. 假设记事本PID为1234(需替换为实际PID)
DWORD dwPid = 1234;
// 2. 构建参数并调用OpenProcess
HANDLE hProcess = OpenProcess(
PROCESS_ALL_ACCESS, // 申请所有权限(需管理员运行程序)
FALSE, // 句柄不可继承
dwPid // 目标进程PID
);
// 3. 错误处理
if (hProcess != NULL) {
std::cout << "进程打开成功,句柄:" << hProcess << std::endl;
// 4. 后续操作(如读写内存)...
// 5. 释放句柄
CloseHandle(hProcess);
} else {
std::cout << "进程打开失败,错误码:" << GetLastError() << std::endl;
std::cout << "可能原因:1.PID错误 2.无管理员权限 3.进程已退出" << std::endl;
}
return 0;
}
注意事项
PROCESS_ALL_ACCESS需要程序以管理员身份运行,否则会返回权限不足(错误码5);- 若仅需读取内存,建议使用
PROCESS_VM_READ(低权限,无需管理员); - 打开的进程句柄必须用
CloseHandle释放。
3. CreateThread - 创建新线程
作用说明
在当前进程中创建一个新线程,用于执行异步任务(如后台处理、循环检测)。
参数构建(共6个参数)
| 参数名 | 类型 | 含义与构建规则 |
|---|---|---|
| lpThreadAttributes | LPSECURITY_ATTRIBUTES | 线程安全属性,NULL=默认(不可继承) |
| dwStackSize | SIZE_T | 线程栈大小,0=使用默认大小(1MB) |
| lpStartAddress★ | LPTHREAD_START_ROUTINE | 线程入口函数(回调函数),必须是DWORD WINAPI Func(LPVOID)格式 |
| lpParameter★ | LPVOID | 传递给线程函数的参数(任意类型,需强制转换) |
| dwCreationFlags | DWORD | 创建标志:0=立即运行,CREATE_SUSPENDED=创建后挂起(需ResumeThread启动) |
| lpThreadId | LPDWORD | 输出参数,返回新线程的TID,NULL=不获取TID |
完整示例(创建线程执行后台任务)
cpp
#include <windows.h>
#include <iostream>
#pragma comment(lib, "kernel32.lib")
// 1. 定义线程入口函数(必须符合格式)
DWORD WINAPI ThreadProc(LPVOID lpParam) {
// 获取传递的参数
std::string strMsg = (const char*)lpParam;
for (int i = 0; i < 5; i++) {
std::cout << "线程执行中:" << strMsg << ",次数:" << i+1 << std::endl;
Sleep(1000); // 暂停1秒
}
return 0; // 线程退出码
}
int main() {
// 2. 构建线程参数
const char* szParam = "Hello Thread";
// 3. 创建线程
HANDLE hThread = CreateThread(
NULL, // 安全属性默认
0, // 默认栈大小
ThreadProc, // 线程入口函数
(LPVOID)szParam, // 传递给线程的参数
0, // 立即运行
NULL // 不获取TID
);
// 4. 错误处理
if (hThread != NULL) {
std::cout << "线程创建成功!" << std::endl;
// 5. 等待线程执行完成(可选)
WaitForSingleObject(hThread, INFINITE); // 无限等待
// 6. 释放线程句柄
CloseHandle(hThread);
} else {
std::cout << "线程创建失败,错误码:" << GetLastError() << std::endl;
}
std::cout << "主线程执行完成!" << std::endl;
return 0;
}
注意事项
- 线程入口函数的参数
lpParam可传递任意类型数据(如结构体、字符串),需做好类型转换; - 线程执行完成后必须释放句柄,否则会造成句柄泄漏;
- 若线程中操作主线程的变量,需加锁(如临界区)避免竞态条件。
4. WaitForSingleObject - 等待内核对象触发
作用说明
等待指定的内核对象(进程、线程、事件、互斥量等)进入"已触发"状态(如进程退出、线程完成),是同步的核心函数。
参数构建(共3个参数)
| 参数名 | 类型 | 含义与构建规则 |
|---|---|---|
| hHandle★ | HANDLE | 要等待的内核对象句柄(进程、线程、事件等) |
| dwMilliseconds★ | DWORD | 等待超时时间:INFINITE=无限等待,0=立即返回,数值=毫秒数(如5000=5秒) |
完整示例(等待进程退出)
cpp
#include <windows.h>
#include <iostream>
#pragma comment(lib, "kernel32.lib")
int main() {
STARTUPINFOW si = {0};
si.cb = sizeof(STARTUPINFOW);
PROCESS_INFORMATION pi = {0};
// 启动记事本进程
CreateProcessW(L"notepad.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
if (pi.hProcess == NULL) {
std::cout << "进程启动失败!" << std::endl;
return 1;
}
std::cout << "等待记事本进程退出(最多10秒)..." << std::endl;
// 等待进程退出(超时10秒)
DWORD dwRet = WaitForSingleObject(
pi.hProcess, // 进程句柄
10000 // 超时10秒
);
// 解析等待结果
switch (dwRet) {
case WAIT_OBJECT_0:
std::cout << "记事本进程已退出!" << std::endl;
break;
case WAIT_TIMEOUT:
std::cout << "等待超时,强制终止进程!" << std::endl;
TerminateProcess(pi.hProcess, 0); // 强制终止进程
break;
case WAIT_FAILED:
std::cout << "等待失败,错误码:" << GetLastError() << std::endl;
break;
}
// 释放句柄
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}
注意事项
- 等待的对象必须是内核对象(进程、线程、事件、互斥量等),普通GDI对象(画笔、画刷)无效;
WAIT_OBJECT_0表示对象正常触发,WAIT_TIMEOUT表示超时,WAIT_FAILED表示等待失败;- 无限等待(INFINITE)需谨慎使用,避免程序卡死。
二、内存操作类函数
1. VirtualAlloc - 分配虚拟内存
作用说明
在当前进程的地址空间中分配虚拟内存,可用于大块内存分配(如缓存、数据存储),是Windows底层内存分配函数。
参数构建(共5个参数)
| 参数名 | 类型 | 含义与构建规则 |
|---|---|---|
| lpAddress | LPVOID | 要分配的内存起始地址,NULL=系统自动分配(推荐) |
| dwSize★ | SIZE_T | 分配的内存大小(字节),需是页面大小的整数倍(通常4096字节) |
| flAllocationType★ | DWORD | 分配类型:MEM_COMMIT=提交内存(可用),MEM_RESERVE=保留地址空间(不可用),MEM_COMMIT |
| flProtect★ | DWORD | 内存保护属性:PAGE_READWRITE=可读可写,PAGE_READONLY=只读,PAGE_EXECUTE_READWRITE=可执行可读可写 |
完整示例(分配可读写虚拟内存)
cpp
#include <windows.h>
#include <iostream>
#include <string.h>
#pragma comment(lib, "kernel32.lib")
int main() {
// 1. 构建参数并分配虚拟内存(4KB)
LPVOID pMem = VirtualAlloc(
NULL, // 系统自动分配地址
4096, // 分配4KB(页面大小)
MEM_COMMIT | MEM_RESERVE, // 提交+保留
PAGE_READWRITE // 可读可写
);
// 2. 错误处理
if (pMem != NULL) {
std::cout << "内存分配成功,地址:" << pMem << std::endl;
// 3. 使用内存(写入数据)
const char* szData = "Hello VirtualAlloc";
memcpy(pMem, szData, strlen(szData) + 1); // 写入字符串(含结束符)
// 4. 读取内存并输出
std::cout << "内存内容:" << (char*)pMem << std::endl;
// 5. 释放内存(必须!)
BOOL bFree = VirtualFree(
pMem, // 要释放的内存地址
0, // 0表示释放整个区域
MEM_RELEASE // 释放保留的地址空间
);
if (bFree) {
std::cout << "内存释放成功!" << std::endl;
} else {
std::cout << "内存释放失败,错误码:" << GetLastError() << std::endl;
}
} else {
std::cout << "内存分配失败,错误码:" << GetLastError() << std::endl;
}
return 0;
}
注意事项
- 分配的内存大小建议为页面大小(4096字节)的整数倍,否则系统会自动向上取整;
PAGE_EXECUTE_READWRITE权限需要管理员权限,用于分配可执行的内存(如动态代码);- 释放时
dwSize必须为0,且dwFreeType为MEM_RELEASE,否则释放失败。
2. ReadProcessMemory - 读取其他进程的内存
作用说明
从指定进程的内存地址中读取数据到当前进程的内存空间,需先通过OpenProcess获取目标进程的句柄和读写权限。
参数构建(共5个参数)
| 参数名 | 类型 | 含义与构建规则 |
|---|---|---|
| hProcess★ | HANDLE | 目标进程的句柄(需有PROCESS_VM_READ权限) |
| lpBaseAddress★ | LPCVOID | 目标进程中要读取的内存起始地址(需知道具体地址,可通过逆向、调试获取) |
| lpBuffer★ | LPVOID | 当前进程中接收数据的缓冲区地址 |
| dwSize★ | SIZE_T | 要读取的字节数 |
| lpNumberOfBytesRead | SIZE_T* | 输出参数,返回实际读取的字节数,NULL=不获取 |
完整示例(读取记事本进程的内存)
cpp
#include <windows.h>
#include <iostream>
#pragma comment(lib, "kernel32.lib")
int main() {
// 1. 打开目标进程(假设记事本PID为1234,需替换)
DWORD dwPid = 1234;
HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, dwPid);
if (hProcess == NULL) {
std::cout << "打开进程失败,错误码:" << GetLastError() << std::endl;
return 1;
}
// 2. 构建参数(假设目标内存地址为0x00400000,需替换为实际地址)
LPCVOID pRemoteAddr = (LPCVOID)0x00400000; // 目标进程内存地址
char szBuf[1024] = {0}; // 接收缓冲区
SIZE_T dwRead = 0; // 实际读取字节数
// 3. 读取目标进程内存
BOOL bRet = ReadProcessMemory(
hProcess, // 目标进程句柄
pRemoteAddr, // 目标内存地址
szBuf, // 接收缓冲区
sizeof(szBuf), // 要读取的字节数
&dwRead // 实际读取字节数
);
// 4. 结果处理
if (bRet) {
std::cout << "内存读取成功,实际读取:" << dwRead << "字节" << std::endl;
std::cout << "内存内容:" << szBuf << std::endl;
} else {
std::cout << "内存读取失败,错误码:" << GetLastError() << std::endl;
std::cout << "可能原因:1.内存地址无效 2.无读取权限 3.进程已退出" << std::endl;
}
// 5. 释放句柄
CloseHandle(hProcess);
return 0;
}
注意事项
- 目标内存地址必须是有效地址(可通过调试器、逆向工具获取),否则读取失败;
- 若目标进程是64位,当前进程也需编译为64位,否则地址空间不匹配;
- 仅能读取已提交的内存(MEM_COMMIT),保留内存(MEM_RESERVE)无法读取。
3. WriteProcessMemory - 写入其他进程的内存
作用说明
将当前进程的数据写入指定进程的内存地址,需目标进程有PROCESS_VM_WRITE和PROCESS_VM_OPERATION权限。
参数构建(共5个参数)
| 参数名 | 类型 | 含义与构建规则 |
|---|---|---|
| hProcess★ | HANDLE | 目标进程句柄(需有PROCESS_VM_WRITE |
| lpBaseAddress★ | LPVOID | 目标进程中要写入的内存起始地址 |
| lpBuffer★ | LPCVOID | 当前进程中要写入的数据缓冲区地址 |
| dwSize★ | SIZE_T | 要写入的字节数 |
| lpNumberOfBytesWritten | SIZE_T* | 输出参数,返回实际写入的字节数,NULL=不获取 |
完整示例(写入数据到记事本进程内存)
cpp
#include <windows.h>
#include <iostream>
#include <string.h>
#pragma comment(lib, "kernel32.lib")
int main() {
// 1. 打开目标进程(需管理员权限)
DWORD dwPid = 1234;
HANDLE hProcess = OpenProcess(
PROCESS_VM_WRITE | PROCESS_VM_OPERATION, // 写内存+操作权限
FALSE,
dwPid
);
if (hProcess == NULL) {
std::cout << "打开进程失败,错误码:" << GetLastError() << std::endl;
return 1;
}
// 2. 构建参数
LPVOID pRemoteAddr = (LPVOID)0x00400000; // 目标内存地址
const char* szData = "Hello WriteProcessMemory"; // 要写入的数据
SIZE_T dwWrite = 0; // 实际写入字节数
// 3. 写入目标进程内存
BOOL bRet = WriteProcessMemory(
hProcess, // 目标进程句柄
pRemoteAddr, // 目标内存地址
szData, // 要写入的数据
strlen(szData) + 1, // 写入字节数(含结束符)
&dwWrite // 实际写入字节数
);
// 4. 结果处理
if (bRet) {
std::cout << "内存写入成功,实际写入:" << dwWrite << "字节" << std::endl;
} else {
std::cout << "内存写入失败,错误码:" << GetLastError() << std::endl;
}
// 5. 释放句柄
CloseHandle(hProcess);
return 0;
}
注意事项
- 必须以管理员身份运行程序,否则权限不足;
- 目标内存地址需有可写权限(PAGE_READWRITE),否则写入失败;
- 写入的数据长度不能超过目标内存区域的大小,否则会导致目标进程崩溃。
三、文件IO类函数
1. CreateFileW - 创建/打开文件/设备
作用说明
Windows中所有"可读写的对象"(文件、管道、串口、磁盘)都可通过该函数打开/创建,是文件IO的核心入口。
参数构建(共7个核心参数)
| 参数名 | 类型 | 含义与构建规则 |
|---|---|---|
| lpFileName★ | LPCWSTR | 要打开/创建的文件路径(如L"test.txt") |
| dwDesiredAccess★ | DWORD | 访问权限:GENERIC_READ=只读,GENERIC_WRITE=只写,GENERIC_READ |
| dwShareMode★ | DWORD | 共享模式:0=独占(其他程序无法打开),FILE_SHARE_READ=允许其他程序读,FILE_SHARE_WRITE=允许其他程序写 |
| lpSecurityAttributes | LPSECURITY_ATTRIBUTES | 安全属性,NULL=默认 |
| dwCreationDisposition★ | DWORD | 创建方式:CREATE_NEW=新建(文件存在则失败),CREATE_ALWAYS=新建(覆盖已有),OPEN_EXISTING=打开(不存在则失败),OPEN_ALWAYS=打开(不存在则新建) |
| dwFlagsAndAttributes★ | DWORD | 文件属性:FILE_ATTRIBUTE_NORMAL=普通文件,FILE_ATTRIBUTE_HIDDEN=隐藏文件,FILE_FLAG_OVERLAPPED=异步IO |
| hTemplateFile | HANDLE | 模板文件句柄,NULL=无 |
完整示例(创建并打开test.txt文件)
cpp
#include <windows.h>
#include <iostream>
#pragma comment(lib, "kernel32.lib")
int main() {
// 1. 构建参数并打开/创建文件
HANDLE hFile = CreateFileW(
L"test.txt", // 文件路径
GENERIC_READ | GENERIC_WRITE, // 读写权限
0, // 独占模式
NULL, // 安全属性默认
CREATE_ALWAYS, // 新建(覆盖已有)
FILE_ATTRIBUTE_NORMAL, // 普通文件
NULL // 无模板文件
);
// 2. 错误处理
if (hFile != INVALID_HANDLE_VALUE) {
std::cout << "文件打开/创建成功!" << std::endl;
// 3. 写入数据
const char* szData = "Hello CreateFileW";
DWORD dwWrite = 0;
WriteFile(hFile, szData, strlen(szData) + 1, &dwWrite, NULL);
std::cout << "写入字节数:" << dwWrite << std::endl;
// 4. 关闭文件句柄(必须!)
CloseHandle(hFile);
} else {
std::cout << "文件打开失败,错误码:" << GetLastError() << std::endl;
}
return 0;
}
注意事项
- 函数返回
INVALID_HANDLE_VALUE表示失败,而非NULL; CREATE_ALWAYS会覆盖已有文件,慎用,建议优先使用OPEN_ALWAYS;- 打开文件后必须用
CloseHandle关闭句柄,否则文件会被锁定。
2. FindFirstFileW & FindNextFileW - 遍历文件/目录
作用说明
FindFirstFileW查找指定路径下的第一个文件/目录,FindNextFileW遍历剩余文件/目录,是批量处理文件的核心函数。
参数构建
| 函数名 | 参数名 | 类型 | 含义与构建规则 |
|---|---|---|---|
| FindFirstFileW | lpFileName★ | LPCWSTR | 查找路径(支持通配符,如L"*.txt") |
| lpFindFileData★ | LPWIN32_FIND_DATAW | 输出参数,返回文件/目录信息,需初始化 | |
| FindNextFileW | hFindFile★ | HANDLE | FindFirstFileW返回的查找句柄 |
| lpFindFileData★ | LPWIN32_FIND_DATAW | 输出参数,返回下一个文件/目录信息 |
完整示例(遍历当前目录下的所有txt文件)
cpp
#include <windows.h>
#include <iostream>
#pragma comment(lib, "kernel32.lib")
int main() {
// 1. 构建查找参数
WIN32_FIND_DATAW fd = {0}; // 存储文件信息
HANDLE hFind = FindFirstFileW(
L"*.txt", // 查找所有txt文件
&fd // 输出第一个文件信息
);
// 2. 错误处理
if (hFind == INVALID_HANDLE_VALUE) {
std::cout << "未找到txt文件,错误码:" << GetLastError() << std::endl;
return 1;
}
// 3. 遍历所有txt文件
std::cout << "找到的txt文件:" << std::endl;
do {
// 排除.和..目录
if (wcscmp(fd.cFileName, L".") != 0 && wcscmp(fd.cFileName, L"..") != 0) {
// 判断是否为文件(非目录)
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
std::wcout << L" " << fd.cFileName << std::endl;
}
}
} while (FindNextFileW(hFind, &fd)); // 遍历下一个文件
// 4. 检查遍历结束原因(正常结束=ERROR_NO_MORE_FILES)
if (GetLastError() != ERROR_NO_MORE_FILES) {
std::cout << "遍历文件失败,错误码:" << GetLastError() << std::endl;
}
// 5. 关闭查找句柄(必须!)
FindClose(hFind);
return 0;
}
注意事项
- 查找路径支持通配符(
*匹配所有,?匹配单个字符); - 遍历结果会包含
.和..目录,需手动排除; FindClose必须调用,否则会造成句柄泄漏。
四、异步IO类函数
1. CreateIoCompletionPort - 创建IO完成端口
作用说明
IO完成端口(IOCP)是Windows高性能异步IO的核心,用于管理多个文件/套接字的异步IO事件,适用于高并发场景(如服务器)。
参数构建(共4个参数)
| 参数名 | 类型 | 含义与构建规则 |
|---|---|---|
| FileHandle | HANDLE | 要关联的文件/套接字句柄,INVALID_HANDLE_VALUE=创建空的IOCP(不关联任何句柄) |
| ExistingCompletionPort | HANDLE | 已存在的IOCP句柄,NULL=创建新的IOCP |
| CompletionKey★ | ULONG_PTR | 完成键(自定义数据,如客户端ID),用于标识IO事件归属 |
| NumberOfConcurrentThreads★ | DWORD | 并发线程数,0=系统自动分配(推荐,等于CPU核心数) |
完整示例(创建IOCP并关联文件句柄)
cpp
#include <windows.h>
#include <iostream>
#pragma comment(lib, "kernel32.lib")
int main() {
// 1. 创建空的IOCP(不关联任何句柄)
HANDLE hIOCP = CreateIoCompletionPort(
INVALID_HANDLE_VALUE, // 不关联句柄
NULL, // 创建新的IOCP
0, // 完成键默认0
0 // 系统自动分配并发线程数
);
if (hIOCP == NULL) {
std::cout << "IOCP创建失败,错误码:" << GetLastError() << std::endl;
return 1;
}
std::cout << "IOCP创建成功,句柄:" << hIOCP << std::endl;
// 2. 打开文件并关联到IOCP
HANDLE hFile = CreateFileW(
L"test.txt",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // 启用异步IO
NULL
);
if (hFile != INVALID_HANDLE_VALUE) {
// 关联文件句柄到IOCP
HANDLE hAssoc = CreateIoCompletionPort(
hFile, // 要关联的文件句柄
hIOCP, // 已创建的IOCP句柄
(ULONG_PTR)1, // 完成键=1(标识该文件)
0 // 并发线程数不变
);
if (hAssoc == hIOCP) {
std::cout << "文件句柄关联IOCP成功!" << std::endl;
}
CloseHandle(hFile);
}
// 3. 关闭IOCP句柄
CloseHandle(hIOCP);
return 0;
}
注意事项
- 关联的句柄必须启用异步IO(
FILE_FLAG_OVERLAPPED),否则IOCP无法捕获事件; - 完成键(CompletionKey)可自定义(如客户端ID、文件ID),用于区分不同的IO事件;
- IOCP句柄需最后释放,且释放前需确保所有异步IO操作已完成。
总结
- 核心参数规则 :
kernel32.dll函数的核心参数(标★)是调用成功的关键,尤其是结构体的cb成员(如STARTUPINFOW.cb)必须初始化;- 权限类参数(如
dwDesiredAccess)需根据实际需求选择最小权限(如只读内存用PROCESS_VM_READ),避免权限过高导致调用失败。
- 资源释放规则 :
- 所有句柄(进程、线程、文件、IOCP、查找句柄)必须手动释放(
CloseHandle/FindClose),否则造成资源泄漏; - 虚拟内存分配后需用
VirtualFree释放,且dwSize必须为0,dwFreeType为MEM_RELEASE。
- 所有句柄(进程、线程、文件、IOCP、查找句柄)必须手动释放(
- 错误处理规则 :
- 调用函数后必须检查返回值,通过
GetLastError()获取错误码定位问题; - 跨进程操作(如
OpenProcess、ReadProcessMemory)需管理员权限,否则返回错误码5(权限不足)。
- 调用函数后必须检查返回值,通过
你想详细了解ReadProcessMemory函数的所属动态链接库、参数构建、完整使用示例以及关键注意事项------这个函数是Windows跨进程内存读取的核心API,隶属于kernel32.dll,也是逆向分析、进程监控、调试工具开发的核心接口。下面我会从基础信息、参数拆解、实战示例、注意事项四个维度完整讲解,确保你能理解并正确使用。
ReadProcessMemory 核心函数
| 项目 | 详情 |
|---|---|
| 所属DLL | kernel32.dll(Windows内核基础库) |
| 导入库(编译链接) | kernel32.lib(Visual Studio默认自动链接,无需手动添加) |
| 头文件 | <windows.h> |
| 函数原型 | BOOL ReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T dwSize, SIZE_T* lpNumberOfBytesRead); |
| 核心作用 | 从指定的远程进程内存地址中,读取数据到当前进程的内存缓冲区中 |
| 返回值 | TRUE=读取成功,FALSE=读取失败(可通过GetLastError()获取具体错误码) |
二、参数构建(逐参数拆解,核心参数标★)
ReadProcessMemory的参数直接决定读取是否成功,以下是每个参数的含义、构建规则和取值要求:
| 参数名 | 类型 | 含义与构建规则 |
|---|---|---|
| hProcess★ | HANDLE | 远程进程的句柄(必须通过OpenProcess获取,且需包含PROCESS_VM_READ权限) |
| lpBaseAddress★ | LPCVOID | 远程进程中要读取的内存起始地址(需是有效、已提交的内存地址,可通过调试/逆向获取) |
| lpBuffer★ | LPVOID | 当前进程中接收数据的缓冲区地址 (需提前分配,大小不小于dwSize) |
| dwSize★ | SIZE_T | 要从远程进程读取的字节数(需≤缓冲区大小,且≤远程内存区域的有效大小) |
| lpNumberOfBytesRead | SIZE_T* | 输出参数:返回实际读取的字节数(可传NULL,但建议传入以校验读取结果) |
三、完整使用示例(读取记事本进程的内存)
这个示例实现"定位记事本进程→打开进程句柄→读取指定内存地址数据",步骤完整且包含错误处理,可直接编译运行:
cpp
#include <windows.h>
#include <iostream>
#include <cstring>
#pragma comment(lib, "kernel32.lib")
// 读取远程进程内存的封装函数
BOOL ReadRemoteMemory(DWORD dwPid, LPCVOID pRemoteAddr, LPVOID pLocalBuf, SIZE_T dwReadSize, SIZE_T& dwActualRead) {
// 1. 打开远程进程(申请只读内存权限)
HANDLE hProcess = OpenProcess(
PROCESS_VM_READ, // 仅申请读内存权限(最小权限原则)
FALSE, // 句柄不可继承
dwPid // 目标进程PID
);
if (hProcess == NULL) {
std::cout << "打开进程失败,错误码:" << GetLastError() << std::endl;
return FALSE;
}
// 2. 初始化实际读取字节数
dwActualRead = 0;
// 3. 调用ReadProcessMemory读取远程内存(核心步骤)
BOOL bRet = ReadProcessMemory(
hProcess, // 远程进程句柄
pRemoteAddr, // 远程内存起始地址
pLocalBuf, // 本地接收缓冲区
dwReadSize, // 要读取的字节数
&dwActualRead // 输出实际读取的字节数
);
// 4. 结果校验与错误处理
if (!bRet) {
std::cout << "读取内存失败,错误码:" << GetLastError() << std::endl;
CloseHandle(hProcess);
return FALSE;
}
if (dwActualRead != dwReadSize) {
std::cout << "警告:读取字节数不匹配!请求读取" << dwReadSize << "字节,实际读取" << dwActualRead << "字节" << std::endl;
}
// 5. 释放进程句柄(必须!)
CloseHandle(hProcess);
return TRUE;
}
int main() {
// ========== 需替换为实际值 ==========
DWORD dwNotepadPid = 1234; // 记事本进程的PID(任务管理器查看)
LPCVOID pRemoteAddr = (LPCVOID)0x00401000; // 远程进程中要读取的内存地址(需有效)
SIZE_T dwReadSize = 1024; // 要读取的字节数(1KB)
// ===================================
// 1. 分配本地缓冲区(接收读取的数据)
char szLocalBuf[1024] = {0};
SIZE_T dwActualRead = 0;
// 2. 调用封装函数读取远程内存
if (ReadRemoteMemory(dwNotepadPid, pRemoteAddr, szLocalBuf, dwReadSize, dwActualRead)) {
std::cout << "内存读取成功!" << std::endl;
std::cout << "实际读取字节数:" << dwActualRead << std::endl;
std::cout << "读取的内存内容(前100字节):" << std::endl;
// 3. 输出读取的内容(十六进制+字符形式,便于分析)
for (SIZE_T i = 0; i < min(dwActualRead, 100); i++) {
printf("%02X ", (BYTE)szLocalBuf[i]);
if ((i + 1) % 16 == 0) std::cout << std::endl; // 每16字节换行
}
std::cout << std::endl;
// 4. 尝试以字符串形式输出(若内存是文本)
std::cout << "字符串形式(仅有效ASCII):" << szLocalBuf << std::endl;
}
return 0;
}
四、关键注意事项(避坑核心)
-
权限要求
- 调用
OpenProcess时必须申请PROCESS_VM_READ权限(只读),若需同时写内存则加PROCESS_VM_WRITE; - 程序需以管理员身份运行,否则可能因权限不足读取失败(错误码5:ACCESS_DENIED)。
- 调用
-
内存地址有效性
lpBaseAddress必须是远程进程中已提交的内存地址(MEM_COMMIT),保留内存(MEM_RESERVE)或无效地址会导致读取失败(错误码299:仅部分读取,或998:INVALID_ACCESS);- 可通过
VirtualQueryEx先查询远程内存的状态,确认地址有效后再读取。
-
32/64位匹配
- 32位程序只能读取32位进程的内存,64位程序只能读取64位进程的内存;
- 若32位程序读取64位进程,会因地址空间(32位最大4GB)限制导致地址无效。
-
常见错误码及解决方法
错误码 含义 解决方法 5 权限不足 以管理员身份运行程序,或确认 OpenProcess的权限参数正确299 仅部分读取成功 检查远程内存地址是否跨页,或目标地址后续内存未提交 998 无效的内存访问 确认 lpBaseAddress是远程进程的有效地址6 句柄无效 检查 hProcess是否为OpenProcess返回的有效句柄(非NULL) -
资源释放
OpenProcess获取的进程句柄必须用CloseHandle释放,否则会造成句柄泄漏;- 本地缓冲区若为动态分配(如
malloc/VirtualAlloc),读取完成后需释放。
五、进阶扩展(可选)
若需读取"不确定是否有效"的内存地址,可先调用VirtualQueryEx查询远程内存状态:
cpp
// 检查远程内存地址是否有效
MEMORY_BASIC_INFORMATION mbi = {0};
VirtualQueryEx(hProcess, pRemoteAddr, &mbi, sizeof(mbi));
if (mbi.State != MEM_COMMIT || (mbi.Protect & PAGE_NOACCESS)) {
std::cout << "远程内存地址无效(未提交/不可访问)" << std::endl;
CloseHandle(hProcess);
return FALSE;
}
CreateRemoteThread 核心函数
| 项⽬ | 详情 |
|---|---|
| 所属DLL | kernel32.dll |
| 导入库(编译链接) | kernel32.lib(Visual Studio默认链接,无需手动添加) |
| 头文件 | <windows.h> |
| 函数原型(Unicode) | HANDLE CreateRemoteThread(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); |
| 核心作用 | 在指定的远程进程中创建一个新线程(区别于CreateThread:仅创建当前进程线程) |
二、参数构建(逐参数拆解,核心参数标★)
| 参数名 | 类型 | 含义与构建规则 |
|---|---|---|
| hProcess★ | HANDLE | 远程进程的句柄(需通过OpenProcess获取,且必须包含PROCESS_CREATE_THREAD权限) |
| lpThreadAttributes | LPSECURITY_ATTRIBUTES | 线程安全属性,NULL=默认(不可继承) |
| dwStackSize | SIZE_T | 线程栈大小,0=使用系统默认大小(1MB) |
| lpStartAddress★ | LPTHREAD_START_ROUTINE | 远程进程中线程入口函数的地址(最常用:LoadLibraryW的地址,用于DLL注入) |
| lpParameter★ | LPVOID | 传递给远程线程入口函数的参数(如DLL路径的内存地址,需先写入远程进程) |
| dwCreationFlags | DWORD | 创建标志:0=立即运行,CREATE_SUSPENDED=创建后挂起(需ResumeThread启动) |
| lpThreadId | LPDWORD | 输出参数,返回远程线程的TID,NULL=不获取 |
三、典型使用示例(DLL注入,CreateRemoteThread最常用场景)
这个示例实现"将自定义DLL注入到记事本进程",完整展示参数构建和函数调用流程:
cpp
#include <windows.h>
#include <iostream>
#include <string>
#pragma comment(lib, "kernel32.lib")
// 注入DLL到远程进程的函数
BOOL InjectDll(DWORD dwPid, const std::wstring& strDllPath) {
// 1. 打开远程进程(需足够权限)
HANDLE hProcess = OpenProcess(
PROCESS_CREATE_THREAD | // 创建线程权限
PROCESS_VM_WRITE | // 写内存权限
PROCESS_VM_OPERATION, // 内存操作权限
FALSE,
dwPid
);
if (hProcess == NULL) {
std::cout << "打开进程失败,错误码:" << GetLastError() << std::endl;
return FALSE;
}
// 2. 在远程进程中分配内存,存储DLL路径
LPVOID pRemoteBuf = VirtualAllocEx(
hProcess,
NULL,
(strDllPath.length() + 1) * sizeof(wchar_t), // 包含结束符的字节数
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE
);
if (pRemoteBuf == NULL) {
std::cout << "远程内存分配失败,错误码:" << GetLastError() << std::endl;
CloseHandle(hProcess);
return FALSE;
}
// 3. 将DLL路径写入远程进程的内存
SIZE_T dwWrite = 0;
BOOL bWrite = WriteProcessMemory(
hProcess,
pRemoteBuf,
strDllPath.c_str(),
(strDllPath.length() + 1) * sizeof(wchar_t),
&dwWrite
);
if (!bWrite) {
std::cout << "写入DLL路径失败,错误码:" << GetLastError() << std::endl;
VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);
CloseHandle(hProcess);
return FALSE;
}
// 4. 获取LoadLibraryW的地址(kernel32.dll导出,所有进程地址相同)
LPTHREAD_START_ROUTINE pStartAddr = (LPTHREAD_START_ROUTINE)GetProcAddress(
GetModuleHandleW(L"kernel32.dll"),
"LoadLibraryW"
);
if (pStartAddr == NULL) {
std::cout << "获取LoadLibraryW地址失败,错误码:" << GetLastError() << std::endl;
VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);
CloseHandle(hProcess);
return FALSE;
}
// 5. 调用CreateRemoteThread创建远程线程,加载DLL(核心步骤)
HANDLE hRemoteThread = CreateRemoteThread(
hProcess, // 远程进程句柄
NULL, // 线程安全属性默认
0, // 默认栈大小
pStartAddr, // 线程入口:LoadLibraryW
pRemoteBuf, // 参数:远程进程中DLL路径的地址
0, // 立即运行线程
NULL // 不获取线程TID
);
if (hRemoteThread == NULL) {
std::cout << "创建远程线程失败,错误码:" << GetLastError() << std::endl;
VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);
CloseHandle(hProcess);
return FALSE;
}
// 6. 等待远程线程执行完成(LoadLibraryW执行完毕)
WaitForSingleObject(hRemoteThread, INFINITE);
// 7. 释放资源
CloseHandle(hRemoteThread);
VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);
CloseHandle(hProcess);
std::cout << "DLL注入成功!" << std::endl;
return TRUE;
}
int main() {
// 替换为记事本的实际PID(可通过任务管理器查看)
DWORD dwNotepadPid = 1234;
// 替换为你的DLL绝对路径
std::wstring strDllPath = L"C:\\MyInject.dll";
InjectDll(dwNotepadPid, strDllPath);
return 0;
}
四、关键注意事项
- 权限要求 :
- 调用
OpenProcess时必须申请PROCESS_CREATE_THREAD | PROCESS_VM_WRITE | PROCESS_VM_OPERATION权限,且程序需以管理员身份运行,否则会返回错误码5(权限不足)。
- 调用
- 地址兼容性 :
LoadLibraryW在kernel32.dll中,而kernel32.dll在所有进程中的加载地址相同,因此可直接用GetProcAddress获取本地地址作为远程线程入口。
- 64/32位匹配 :
- 32位程序只能注入32位进程,64位程序只能注入64位进程,否则地址空间不匹配,调用失败。
- 资源释放 :
- 远程线程句柄、远程进程句柄、远程分配的内存必须全部释放,避免资源泄漏。
- 替代函数 :
- Windows Vista及以上系统,微软推荐用
CreateRemoteThreadEx(功能更强,支持扩展参数),但核心所属库仍为kernel32.dll。
- Windows Vista及以上系统,微软推荐用
kernel32.dll动态链接库的函数名列表
此库有数千个函数**(覆盖进程、线程、内存、文件、系统交互等所有底层能力),开发中高频使用的核心函数**(优先标注Unicode版本/W后缀)
kernel32.dll 核心函数列表(按功能分类)
| 功能分类 | 函数名 | 核心作用 |
|---|---|---|
| 进程管理 | CreateProcessW | 创建新进程(启动外部可执行文件) |
| OpenProcess | 根据PID打开进程,获取进程句柄(用于跨进程操作) | |
| CloseHandle | 释放进程/线程/文件等内核对象句柄 | |
| TerminateProcess | 强制终止指定进程 | |
| GetCurrentProcess | 获取当前进程的伪句柄 | |
| GetCurrentProcessId | 获取当前进程的PID(进程ID) | |
| GetProcessId | 根据进程句柄获取PID | |
| GetProcessHandleCount | 获取指定进程的句柄数量 | |
| GetProcessPriorityClass | 获取进程的优先级类别(如高/普通/低优先级) | |
| SetProcessPriorityClass | 设置进程的优先级类别 | |
| CreateProcessAsUserW | 以指定用户身份创建进程(需权限) | |
| GetExitCodeProcess | 获取进程的退出码(判断进程是否运行) | |
| DuplicateHandle | 复制进程/线程等内核对象的句柄 | |
| 线程管理 | CreateThread | 在当前进程中创建新线程 |
| CreateRemoteThread | 在远程进程中创建线程(用于DLL注入、远程代码执行) | |
| CreateRemoteThreadEx | 扩展版远程线程创建(支持扩展参数) | |
| OpenThread | 根据TID打开线程,获取线程句柄 | |
| GetCurrentThread | 获取当前线程的伪句柄 | |
| GetCurrentThreadId | 获取当前线程的TID(线程ID) | |
| GetThreadId | 根据线程句柄获取TID | |
| TerminateThread | 强制终止指定线程(慎用,易泄漏资源) | |
| SuspendThread | 挂起指定线程(暂停执行) | |
| ResumeThread | 恢复挂起的线程(继续执行) | |
| GetThreadPriority | 获取线程的优先级 | |
| SetThreadPriority | 设置线程的优先级 | |
| Sleep | 暂停当前线程指定毫秒数 | |
| SwitchToThread | 主动让出CPU时间片给其他线程 | |
| QueueUserAPC | 将APC函数排队到指定线程(异步调用) | |
| 内存操作 | VirtualAlloc | 在当前进程分配虚拟内存 |
| VirtualAllocEx | 在远程进程分配虚拟内存 | |
| VirtualFree | 释放当前进程的虚拟内存 | |
| VirtualFreeEx | 释放远程进程的虚拟内存 | |
| VirtualProtect | 修改当前进程内存的保护属性(读/写/执行) | |
| VirtualProtectEx | 修改远程进程内存的保护属性 | |
| VirtualQuery | 查询当前进程内存的状态(提交/保留/空闲) | |
| VirtualQueryEx | 查询远程进程内存的状态 | |
| HeapAlloc | 从进程堆分配内存 | |
| HeapFree | 释放HeapAlloc分配的堆内存 | |
| HeapCreate | 创建自定义堆 | |
| HeapDestroy | 销毁自定义堆 | |
| HeapReAlloc | 重新分配堆内存(扩容/缩容) | |
| HeapSize | 获取堆内存块的实际大小 | |
| GetProcessHeap | 获取当前进程的默认堆句柄 | |
| ReadProcessMemory | 读取远程进程的内存数据 | |
| WriteProcessMemory | 写入数据到远程进程的内存 | |
| GlobalAlloc | 分配全局内存(兼容16位系统,少用) | |
| GlobalFree | 释放全局内存 | |
| 文件IO | CreateFileW | 打开/创建文件、管道、串口、磁盘等内核对象 |
| ReadFile | 同步读取文件/设备数据 | |
| ReadFileEx | 异步读取文件/设备数据(重叠IO) | |
| WriteFile | 同步写入文件/设备数据 | |
| WriteFileEx | 异步写入文件/设备数据(重叠IO) | |
| CloseHandle | 关闭文件句柄(复用,核心释放函数) | |
| SetFilePointer | 设置文件指针位置(随机读写) | |
| SetFilePointerEx | 扩展版文件指针设置(支持64位偏移) | |
| GetFileSize | 获取文件大小(32位) | |
| GetFileSizeEx | 获取文件大小(64位,推荐) | |
| FlushFileBuffers | 刷新文件缓冲区(强制写入磁盘) | |
| FindFirstFileW | 查找指定路径下的第一个文件/目录 | |
| FindNextFileW | 遍历剩余文件/目录 | |
| FindClose | 关闭文件查找句柄 | |
| CopyFileW | 复制文件 | |
| MoveFileW | 移动/重命名文件 | |
| DeleteFileW | 删除指定文件 | |
| CreateDirectoryW | 创建单个目录 | |
| RemoveDirectoryW | 删除空目录 | |
| GetFileAttributesW | 获取文件/目录的属性(隐藏/只读/系统等) | |
| SetFileAttributesW | 设置文件/目录的属性 | |
| CreateFileMappingW | 创建文件映射(内存映射文件/共享内存) | |
| MapViewOfFile | 将文件映射到进程内存空间 | |
| UnmapViewOfFile | 解除文件映射的内存视图 | |
| 系统信息 | GetVersion | 获取系统版本信息(兼容旧系统) |
| GetVersionExW | 扩展版系统版本获取(推荐) | |
| GetNativeSystemInfo | 获取原生系统信息(区分32/64位) | |
| GetSystemInfo | 获取系统硬件信息(CPU核心数、页面大小等) | |
| GetComputerNameW | 获取计算机名称 | |
| GetUserNameW | 获取当前登录用户名(复用,也在advapi32.dll中) | |
| GetSystemDirectoryW | 获取系统目录路径(如C:\Windows\System32) | |
| GetWindowsDirectoryW | 获取Windows目录路径 | |
| GetCurrentDirectoryW | 获取当前进程的工作目录 | |
| SetCurrentDirectoryW | 设置当前进程的工作目录 | |
| 同步操作 | CreateEventW | 创建事件对象(同步/异步) |
| SetEvent | 设置事件为已触发状态 | |
| ResetEvent | 重置事件为未触发状态 | |
| CreateMutexW | 创建互斥量(进程/线程同步) | |
| ReleaseMutex | 释放互斥量 | |
| CreateSemaphoreW | 创建信号量 | |
| ReleaseSemaphore | 释放信号量 | |
| WaitForSingleObject | 等待单个内核对象触发(进程/线程/事件等) | |
| WaitForMultipleObjects | 等待多个内核对象触发 | |
| WaitForMultipleObjectsEx | 扩展版多对象等待(支持异步) | |
| CreateCriticalSection | 创建临界区(线程同步,用户态) | |
| EnterCriticalSection | 进入临界区 | |
| LeaveCriticalSection | 离开临界区 | |
| DeleteCriticalSection | 销毁临界区 | |
| 模块加载 | LoadLibraryW | 加载DLL模块到进程地址空间 |
| FreeLibrary | 释放已加载的DLL模块 | |
| GetModuleHandleW | 获取已加载模块的句柄(NULL=当前模块) | |
| GetProcAddress | 获取DLL导出函数的地址 | |
| EnumProcessModules | 枚举指定进程的所有加载模块(复用,也在psapi.dll中) | |
| 错误处理 | GetLastError | 获取最近一次API调用的错误码 |
| SetLastError | 设置自定义错误码 | |
| FormatMessageW | 将错误码转换为可读的错误描述 | |
| 时间操作 | GetLocalTime | 获取本地系统时间(年月日时分秒) |
| GetSystemTime | 获取UTC系统时间 | |
| GetTickCount | 获取系统启动后的毫秒数 | |
| GetTickCount64 | 64位版本的系统启动毫秒数(推荐) | |
| QueryPerformanceCounter | 获取高精度性能计数器(用于计时) | |
| QueryPerformanceFrequency | 获取性能计数器的频率 | |
| 环境变量 | GetEnvironmentVariableW | 获取指定环境变量的值 |
| SetEnvironmentVariableW | 设置/删除环境变量 | |
| ExpandEnvironmentStringsW | 展开环境变量字符串(如%PATH%) | |
| IO完成端口 | CreateIoCompletionPort | 创建IO完成端口(高性能异步IO核心) |
| GetQueuedCompletionStatus | 获取IO完成端口的完成事件 | |
| PostQueuedCompletionStatus | 手动投递IO完成事件 | |
| CloseIoCompletionPort | 关闭IO完成端口 | |
| 其他核心 | GetCommandLineW | 获取进程的命令行参数 |
| ExitProcess | 终止当前进程 | |
| ExitThread | 终止当前线程 | |
| IsDebuggerPresent | 判断进程是否被调试器附加 | |
| OutputDebugStringW | 输出调试字符串到调试器 |
总结
- 命名规则 :带
W后缀的为Unicode版本(推荐使用),A后缀为ANSI版本(兼容旧系统),无后缀函数多为通用接口; - 调用前提 :使用这些函数需包含
<windows.h>头文件,链接kernel32.lib(Visual Studio默认自动链接); - 资源管理 :所有返回"句柄"的函数(如
CreateProcessW/CreateFileW),使用后必须调用CloseHandle释放,避免资源泄漏; - 权限注意 :跨进程操作函数(如
OpenProcess/ReadProcessMemory)需管理员权限,否则会返回权限不足(错误码5)。
若需查询kernel32.dll的完整函数列表 ,可通过Windows SDK的dumpbin工具(dumpbin /exports C:\Windows\System32\kernel32.dll)或微软官方文档(Kernel32.dll 函数参考)查看。