PCILeech开发文档:核心API详解与调用示例
1. 概述
PCILeech是一款功能强大的Direct Memory Access (DMA)攻击软件,允许开发者通过PCIe接口直接访问目标系统的物理内存。本文档将深入解析PCILeech的核心API,包括LeechCore和VMMDLL两大模块,并提供详细的调用示例,帮助开发者快速上手并掌握高级应用技巧。
1.1 核心功能
PCILeech主要提供以下核心功能:
- 物理内存直接读写
- 支持多种DMA硬件设备
- 虚拟文件系统(VFS)访问
- 进程和内核信息获取
- 插件扩展机制
1.2 API模块架构
PCILeech的API主要分为两个核心模块:
2. LeechCore API详解
LeechCore是PCILeech的底层核心库,负责抽象不同DMA硬件设备的访问接口,提供统一的内存读写功能。
2.1 设备初始化与关闭
2.1.1 LcCreate
创建并初始化一个LeechCore设备实例。
HANDLE LcCreate(
_Inout_ PLC_CONFIG pLcCreateConfig
);
参数说明:
| 参数名 | 类型 | 描述 |
|---|---|---|
| pLcCreateConfig | PLC_CONFIG | 设备配置结构体指针 |
配置结构体(LC_CONFIG):
typedef struct LC_CONFIG {
DWORD dwVersion; // 必须设置为LC_CONFIG_VERSION
DWORD dwPrintfVerbosity; // 输出详细程度
CHAR szDevice[MAX_PATH]; // 设备配置字符串
CHAR szRemote[MAX_PATH]; // 远程连接配置
int(*pfn_printf_opt)(const char*, ...); // 自定义printf函数
QWORD paMax; // 最大物理地址
BOOL fVolatile; // 由LeechCore设置,表示内存是否易失
BOOL fWritable; // 由LeechCore设置,表示是否可写
BOOL fRemote; // 由LeechCore设置,表示是否远程连接
BOOL fRemoteDisableCompress; // 由LeechCore设置,表示是否禁用压缩
CHAR szDeviceName[MAX_PATH]; // 由LeechCore设置,表示设备名称
} LC_CONFIG, *PLC_CONFIG;
使用示例:
LC_CONFIG config = {0};
config.dwVersion = LC_CONFIG_VERSION;
config.dwPrintfVerbosity = LC_CONFIG_PRINTF_ENABLED | LC_CONFIG_PRINTF_V;
strcpy(config.szDevice, "fpga"); // 使用FPGA设备
HANDLE hLC = LcCreate(&config);
if (!hLC) {
printf("Failed to create LeechCore device\n");
return -1;
}
2.1.2 LcClose
关闭LeechCore设备并释放资源。
VOID LcClose(
_In_opt_ HANDLE hLC
);
参数说明:
| 参数名 | 类型 | 描述 |
|---|---|---|
| hLC | HANDLE | LcCreate返回的设备句柄 |
使用示例:
LcClose(hLC); // 关闭设备
2.2 内存读写操作
2.2.1 连续内存读写
LcRead: 从指定物理地址读取连续内存
BOOL LcRead(
_In_ HANDLE hLC,
_In_ QWORD pa,
_In_ DWORD cb,
_Out_writes_(cb) PBYTE pb
);
参数说明:
| 参数名 | 类型 | 描述 |
|---|---|---|
| hLC | HANDLE | LeechCore设备句柄 |
| pa | QWORD | 物理地址(Physical Address) |
| cb | DWORD | 要读取的字节数 |
| pb | PBYTE | 接收数据的缓冲区指针 |
返回值: 成功返回TRUE,失败返回FALSE
LcWrite: 向指定物理地址写入连续内存
BOOL LcWrite(
_In_ HANDLE hLC,
_In_ QWORD pa,
_In_ DWORD cb,
_In_reads_(cb) PBYTE pb
);
参数说明:
| 参数名 | 类型 | 描述 |
|---|---|---|
| hLC | HANDLE | LeechCore设备句柄 |
| pa | QWORD | 物理地址(Physical Address) |
| cb | DWORD | 要写入的字节数 |
| pb | PBYTE | 包含要写入数据的缓冲区指针 |
返回值: 成功返回TRUE,失败返回FALSE
使用示例:
BYTE buffer[0x1000]; // 4KB缓冲区
QWORD address = 0x100000; // 要读取的物理地址
// 读取内存
if (!LcRead(hLC, address, sizeof(buffer), buffer)) {
printf("Failed to read memory\n");
return -1;
}
// 修改数据
memset(buffer, 0xCC, sizeof(buffer));
// 写入内存
if (!LcWrite(hLC, address, sizeof(buffer), buffer)) {
printf("Failed to write memory\n");
return -1;
}
2.2.2 分散内存读写
对于需要读写多个不连续内存块的场景,LeechCore提供了分散读写(scatter)功能,这比多次调用连续读写更高效。
LcAllocScatter1: 分配分散内存结构
BOOL LcAllocScatter1(
_In_ DWORD cMEMs,
_Out_ PPMEM_SCATTER *pppMEMs
);
参数说明:
| 参数名 | 类型 | 描述 |
|---|---|---|
| cMEMs | DWORD | 要分配的内存块数量 |
| pppMEMs | PPMEM_SCATTER* | 用于接收分配的MEM_SCATTER数组 |
MEM_SCATTER结构:
typedef struct tdMEM_SCATTER {
DWORD version; // 必须设置为MEM_SCATTER_VERSION
BOOL f; // 操作结果,TRUE表示成功
QWORD qwA; // 物理地址
union {
PBYTE pb; // 数据缓冲区
QWORD _Filler;
};
DWORD cb; // 数据大小
DWORD iStack; // 内部堆栈指针
QWORD vStack[MEM_SCATTER_STACK_SIZE]; // 内部堆栈
} MEM_SCATTER, *PMEM_SCATTER;
LcReadScatter: 读取多个分散的内存块
VOID LcReadScatter(
_In_ HANDLE hLC,
_In_ DWORD cMEMs,
_Inout_ PPMEM_SCATTER ppMEMs
);
参数说明:
| 参数名 | 类型 | 描述 |
|---|---|---|
| hLC | HANDLE | LeechCore设备句柄 |
| cMEMs | DWORD | 内存块数量 |
| ppMEMs | PPMEM_SCATTER | MEM_SCATTER结构体数组 |
LcWriteScatter: 写入多个分散的内存块
VOID LcWriteScatter(
_In_ HANDLE hLC,
_In_ DWORD cMEMs,
_Inout_ PPMEM_SCATTER ppMEMs
);
参数说明:与LcReadScatter相同
LcMemFree: 释放由LeechCore分配的内存
VOID LcMemFree(
_Frees_ptr_opt_ PVOID pv
);
使用示例:
PPMEM_SCATTER ppMEMs = NULL;
DWORD cMEMs = 3; // 读取3个分散的内存块
// 分配内存结构
if (!LcAllocScatter1(cMEMs, &ppMEMs)) {
printf("Failed to allocate scatter memory\n");
return -1;
}
// 设置要读取的内存块
ppMEMs[0]->version = MEM_SCATTER_VERSION;
ppMEMs[0]->qwA = 0x100000; // 第一个内存块地址
ppMEMs[0]->cb = 0x1000; // 4KB
ppMEMs[1]->version = MEM_SCATTER_VERSION;
ppMEMs[1]->qwA = 0x200000; // 第二个内存块地址
ppMEMs[1]->cb = 0x1000; // 4KB
ppMEMs[2]->version = MEM_SCATTER_VERSION;
ppMEMs[2]->qwA = 0x300000; // 第三个内存块地址
ppMEMs[2]->cb = 0x1000; // 4KB
// 读取分散内存
LcReadScatter(hLC, cMEMs, ppMEMs);
// 检查结果并处理数据
for (DWORD i = 0; i < cMEMs; i++) {
if (ppMEMs[i]->f) {
printf("Read memory block %d: 0x%llX, size: %d bytes\n",
i, ppMEMs[i]->qwA, ppMEMs[i]->cb);
// 处理ppMEMs[i]->pb中的数据
} else {
printf("Failed to read memory block %d\n", i);
}
}
// 释放内存
LcMemFree(ppMEMs);
2.3 设备配置与控制
LeechCore提供了获取和设置设备选项的功能,以及执行特定命令的接口。
2.3.1 LcGetOption和LcSetOption
获取和设置设备选项。
BOOL LcGetOption(
_In_ HANDLE hLC,
_In_ QWORD fOption,
_Out_ PQWORD pqwValue
);
BOOL LcSetOption(
_In_ HANDLE hLC,
_In_ QWORD fOption,
_In_ QWORD qwValue
);
常用选项:
| 选项常量 | 类型 | 描述 |
|---|---|---|
| LC_OPT_CORE_PRINTF_ENABLE | RW | 启用/禁用输出 |
| LC_OPT_CORE_VERBOSE | RW | 详细输出级别 |
| LC_OPT_CORE_VERSION_MAJOR | R | 获取主版本号 |
| LC_OPT_CORE_VERSION_MINOR | R | 获取次版本号 |
| LC_OPT_CORE_ADDR_MAX | R | 获取最大物理地址 |
| LC_OPT_FPGA_PROBE_MAXPAGES | RW | FPGA探测的最大页数 |
| LC_OPT_FPGA_MAX_SIZE_RX | RW | FPGA接收缓冲区大小 |
| LC_OPT_FPGA_MAX_SIZE_TX | RW | FPGA发送缓冲区大小 |
使用示例:
QWORD qwValue;
// 获取最大物理地址
if (LcGetOption(hLC, LC_OPT_CORE_ADDR_MAX, &qwValue)) {
printf("Maximum physical address: 0x%llX\n", qwValue);
}
// 设置FPGA接收缓冲区大小
if (!LcSetOption(hLC, LC_OPT_FPGA_MAX_SIZE_RX, 0x10000)) { // 64KB
printf("Failed to set FPGA RX buffer size\n");
}
2.3.2 LcCommand
执行特定设备命令。
BOOL LcCommand(
_In_ HANDLE hLC,
_In_ QWORD fCommand,
_In_ DWORD cbDataIn,
_In_reads_opt_(cbDataIn) PBYTE pbDataIn,
_Out_opt_ PBYTE *ppbDataOut,
_Out_opt_ PDWORD pcbDataOut
);
常用命令:
| 命令常量 | 描述 |
|---|---|
| LC_CMD_FPGA_PCIECFGSPACE | 读取PCIe配置空间 |
| LC_CMD_FPGA_CFGREGPCIE | 读取/写入PCIe配置寄存器 |
| LC_CMD_FPGA_PROBE | 执行FPGA探测 |
| LC_CMD_FILE_DUMPHEADER_GET | 获取文件转储头信息 |
| LC_CMD_STATISTICS_GET | 获取统计信息 |
使用示例:
PBYTE pbOut = NULL;
DWORD cbOut = 0;
// 获取统计信息
if (LcCommand(hLC, LC_CMD_STATISTICS_GET, 0, NULL, &pbOut, &cbOut)) {
LC_STATISTICS *pStats = (LC_STATISTICS *)pbOut;
if (pStats->dwVersion == LC_STATISTICS_VERSION) {
printf("LeechCore Statistics:\n");
for (DWORD i = 0; i <= LC_STATISTICS_ID_MAX; i++) {
printf(" %s: Calls: %lld, Time: %lld\n",
LC_STATISTICS_NAME[i],
pStats->Call[i].c,
pStats->Call[i].tm);
}
}
LcMemFree(pbOut); // 释放由LcCommand分配的内存
}
3. VMMDLL API详解
VMMDLL提供了更高级的内存分析功能,包括虚拟内存访问、进程枚举、文件系统模拟等。它构建在LeechCore之上,提供了更友好的接口。
3.1 VMM初始化与关闭
3.1.1 VMMDLL_Initialize
初始化VMMDLL实例。
VMM_HANDLE VMMDLL_Initialize(
_In_ DWORD argc,
_In_ LPCSTR argv[]
);
参数说明:
| 参数名 | 类型 | 描述 |
|---|---|---|
| argc | DWORD | 命令行参数数量 |
| argv | LPCSTR[] | 命令行参数数组 |
常用命令行参数:
| 参数 | 描述 |
|---|---|
| -device | 指定设备类型,如"fpga"、"usb3380"、"file"等 |
| -remote | 连接到远程LeechCore实例 |
| -v/-vv/-vvv | 详细输出级别 |
| -memmap | 指定内存映射文件或使用"auto"自动检测 |
| -pagefile | 指定页面文件 |
| -forensic | 启用取证模式 |
使用示例:
// 使用FPGA设备初始化VMM
const char *argv[] = {
"vmm.dll",
"-device", "fpga",
"-v", // 启用详细输出
"-memmap", "auto" // 自动检测内存映射
};
DWORD argc = sizeof(argv) / sizeof(argv[0]);
VMM_HANDLE hVMM = VMMDLL_Initialize(argc, argv);
if (!hVMM) {
printf("Failed to initialize VMM\n");
return -1;
}
3.1.2 VMMDLL_Close
关闭VMMDLL实例并释放资源。
VOID VMMDLL_Close(
_In_opt_ VMM_HANDLE hVMM
);
使用示例:
VMMDLL_Close(hVMM); // 关闭VMM实例
3.2 系统配置与信息
3.2.1 VMMDLL_ConfigGet和VMMDLL_ConfigSet
获取和设置VMM配置选项。
BOOL VMMDLL_ConfigGet(
_In_ VMM_HANDLE hVMM,
_In_ ULONG64 fOption,
_Out_ PULONG64 pqwValue
);
BOOL VMMDLL_ConfigSet(
_In_ VMM_HANDLE hVMM,
_In_ ULONG64 fOption,
_In_ ULONG64 qwValue
);
常用配置选项:
| 选项常量 | 类型 | 描述 |
|---|---|---|
| VMMDLL_OPT_CORE_PRINTF_ENABLE | RW | 启用/禁用输出 |
| VMMDLL_OPT_CORE_VERBOSE | RW | 详细输出级别 |
| VMMDLL_OPT_CONFIG_TICK_PERIOD | RW | 基础时钟周期(ms) |
| VMMDLL_OPT_CONFIG_READCACHE_TICKS | RW | 内存缓存有效期(ticks) |
| VMMDLL_OPT_WIN_VERSION_MAJOR | R | Windows主版本号 |
| VMMDLL_OPT_WIN_VERSION_MINOR | R | Windows次版本号 |
| VMMDLL_OPT_WIN_VERSION_BUILD | R | Windows构建号 |
使用示例:
ULONG64 qwValue;
// 获取Windows版本信息
if (VMMDLL_ConfigGet(hVMM, VMMDLL_OPT_WIN_VERSION_MAJOR, &qwValue)) {
printf("Windows Version Major: %lld\n", qwValue);
}
if (VMMDLL_ConfigGet(hVMM, VMMDLL_OPT_WIN_VERSION_MINOR, &qwValue)) {
printf("Windows Version Minor: %lld\n", qwValue);
}
if (VMMDLL_ConfigGet(hVMM, VMMDLL_OPT_WIN_VERSION_BUILD, &qwValue)) {
printf("Windows Build Number: %lld\n", qwValue);
}
// 设置内存缓存有效期为5个时钟周期
VMMDLL_ConfigSet(hVMM, VMMDLL_OPT_CONFIG_READCACHE_TICKS, 5);
3.3 虚拟文件系统(VFS)操作
VMMDLL提供了访问目标系统文件系统的接口,通过虚拟文件系统(VFS)抽象,可以像访问本地文件一样访问目标系统的文件。
3.3.1 VMMDLL_VfsListU
列出指定目录下的文件和子目录。
_Success_(return) BOOL VMMDLL_VfsListU(
_In_ VMM_HANDLE hVMM,
_In_ LPCSTR uszPath,
_Inout_ PVMMDLL_VFS_FILELIST2 pFileList
);
使用示例:
VMMDLL_VFS_FILELIST2 fileList = {0};
fileList.dwVersion = VMMDLL_VFS_FILELIST_VERSION;
// 定义回调函数来处理列出的文件
fileList.pfnAddFile = [](HANDLE h, LPCSTR name, ULONG64 size, PVMMDLL_VFS_FILELIST_EXINFO ex) {
printf("File: %s, Size: %lld bytes\n", name, size);
};
fileList.pfnAddDirectory = [](HANDLE h, LPCSTR name, PVMMDLL_VFS_FILELIST_EXINFO ex) {
printf("Directory: %s\n", name);
};
// 列出目标系统的C盘根目录
if (VMMDLL_VfsListU(hVMM, "/files/c/", &fileList)) {
printf("Successfully listed directory\n");
} else {
printf("Failed to list directory\n");
}
3.3.2 VMMDLL_VfsReadU和VMMDLL_VfsWriteU
读取和写入目标系统的文件。
NTSTATUS VMMDLL_VfsReadU(
_In_ VMM_HANDLE hVMM,
_In_ LPCSTR uszFileName,
_Out_writes_to_(cb, *pcbRead) PBYTE pb,
_In_ DWORD cb,
_Out_ PDWORD pcbRead,
_In_ ULONG64 cbOffset
);
NTSTATUS VMMDLL_VfsWriteU(
_In_ VMM_HANDLE hVMM,
_In_ LPCSTR uszFileName,
_In_reads_(cb) PBYTE pb,
_In_ DWORD cb,
_Out_ PDWORD pcbWrite,
_In_ ULONG64 cbOffset
);
返回值(NTSTATUS):
| 状态码 | 描述 |
|---|---|
| VMMDLL_STATUS_SUCCESS (0x00000000) | 操作成功 |
| VMMDLL_STATUS_UNSUCCESSFUL (0xC0000001) | 操作失败 |
| VMMDLL_STATUS_END_OF_FILE (0xC0000011) | 已到达文件末尾 |
| VMMDLL_STATUS_FILE_INVALID (0xC0000098) | 文件无效 |
使用示例:
// 读取目标系统的注册表文件
BYTE buffer[4096];
DWORD cbRead;
NTSTATUS status = VMMDLL_VfsReadU(
hVMM,
"/files/c/windows/system32/config/SYSTEM",
buffer,
sizeof(buffer),
&cbRead,
0 // 从文件开头读取
);
if (status == VMMDLL_STATUS_SUCCESS) {
printf("Read %d bytes from registry file\n", cbRead);
// 处理读取的数据
} else {
printf("Failed to read file, status: 0x%X\n", status);
}
4. 高级应用示例
4.1 物理内存转储工具
以下示例展示了如何使用LeechCore API创建一个简单的物理内存转储工具。
#include <stdio.h>
#include <stdlib.h>
#include "leechcore.h"
#define BUFFER_SIZE 0x100000 // 1MB缓冲区
#define PROGRESS_STEP 0x1000000 // 每16MB显示一次进度
int main() {
// 初始化LeechCore配置
LC_CONFIG config = {0};
config.dwVersion = LC_CONFIG_VERSION;
config.dwPrintfVerbosity = LC_CONFIG_PRINTF_ENABLED | LC_CONFIG_PRINTF_V;
strcpy(config.szDevice, "fpga"); // 使用FPGA设备
// 创建LeechCore设备
HANDLE hLC = LcCreate(&config);
if (!hLC) {
printf("Failed to create LeechCore device\n");
return 1;
}
// 获取最大物理地址
QWORD paMax;
if (!LcGetOption(hLC, LC_OPT_CORE_ADDR_MAX, &paMax)) {
printf("Failed to get maximum physical address\n");
LcClose(hLC);
return 1;
}
printf("Dumping physical memory from 0x0 to 0x%llX...\n", paMax);
// 打开输出文件
FILE *pFile = fopen("memory_dump.bin", "wb");
if (!pFile) {
printf("Failed to open output file\n");
LcClose(hLC);
return 1;
}
// 分配缓冲区
BYTE *pBuffer = (BYTE *)malloc(BUFFER_SIZE);
if (!pBuffer) {
printf("Failed to allocate buffer\n");
fclose(pFile);
LcClose(hLC);
return 1;
}
// 转储内存
QWORD pa = 0;
DWORD progress = 0;
while (pa < paMax) {
DWORD cbToRead = (DWORD)min(BUFFER_SIZE, paMax - pa);
// 读取内存
if (!LcRead(hLC, pa, cbToRead, pBuffer)) {
printf("Failed to read memory at 0x%llX\n", pa);
// 可以选择跳过错误继续
pa += cbToRead;
continue;
}
// 写入文件
fwrite(pBuffer, 1, cbToRead, pFile);
// 显示进度
pa += cbToRead;
if (pa / PROGRESS_STEP > progress) {
progress = pa / PROGRESS_STEP;
printf("Progress: %d%%\r", (int)((pa * 100) / paMax));
fflush(stdout);
}
}
printf("\nDump completed successfully\n");
// 清理资源
free(pBuffer);
fclose(pFile);
LcClose(hLC);
return 0;
}
4.2 远程文件浏览器
以下示例展示了如何使用VMMDLL的VFS功能创建一个简单的远程文件浏览器。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vmmdll.h"
// 递归列出目录内容
void list_directory(VMM_HANDLE hVMM, const char *path, int depth) {
VMMDLL_VFS_FILELIST2 fileList = {0};
fileList.dwVersion = VMMDLL_VFS_FILELIST_VERSION;
// 缩进显示,直观表示目录层级
char indent[256] = {0};
for (int i = 0; i < depth; i++) {
strcat(indent, " ");
}
// 文件和目录回调函数
fileList.pfnAddFile = [](HANDLE h, LPCSTR name, ULONG64 size, PVMMDLL_VFS_FILELIST_EXINFO ex) {
char *indent = (char *)h; // 使用h传递indent
printf("%s- %s (%lld bytes)\n", indent, name, size);
};
fileList.pfnAddDirectory = [](HANDLE h, LPCSTR name, PVMMDLL_VFS_FILELIST_EXINFO ex) {
char *indent = (char *)h; // 使用h传递indent
char subpath[1024];
snprintf(subpath, sizeof(subpath), "%s%s/", (const char *)h + 256, name); // h前256字节是indent,后面是路径
printf("%s+ %s/\n", indent, name);
// 递归列出子目录
list_directory(*(VMM_HANDLE *)(h + 512), subpath, strlen(indent)/2 + 1);
};
// 使用h参数传递额外数据:indent(256字节)、当前路径(256字节)、VMM句柄(8字节)
char extra_data[256 + 256 + sizeof(VMM_HANDLE)];
strncpy(extra_data, indent, 256);
strncpy(extra_data + 256, path, 256);
*(VMM_HANDLE *)(extra_data + 512) = hVMM;
fileList.h = (HANDLE)extra_data;
// 列出目录
if (!VMMDLL_VfsListU(hVMM, path, &fileList)) {
printf("%sFailed to list directory: %s\n", indent, path);
}
}
int main() {
// 初始化VMMDLL
const char *argv[] = {
"vmm.dll",
"-device", "fpga",
"-v"
};
DWORD argc = sizeof(argv) / sizeof(argv[0]);
VMM_HANDLE hVMM = VMMDLL_Initialize(argc, argv);
if (!hVMM) {
printf("Failed to initialize VMM\n");
return 1;
}
printf("Remote File Browser\n");
printf("===================\n");
list_directory(hVMM, "/files/c/", 0);
VMMDLL_Close(hVMM);
return 0;
}
5. 常见问题与解决方案
5.1 设备初始化失败
问题描述:调用LcCreate或VMMDLL_Initialize返回NULL。
可能原因与解决方案:
- 设备未连接:确保DMA设备已正确连接到系统。
- 驱动未安装:对于某些设备,需要安装特定驱动。
- 权限不足:尝试以管理员权限运行程序。
- 设备被占用:确保没有其他程序正在使用该DMA设备。
- 配置错误:检查设备配置字符串是否正确。
5.2 内存读写失败
问题描述:LcRead或LcWrite返回FALSE,或VMMDLL_VfsReadU返回错误状态码。
可能原因与解决方案:
-
地址无效:验证访问的物理地址是否在有效范围内。
QWORD paMax; LcGetOption(hLC, LC_OPT_CORE_ADDR_MAX, &paMax); if (address >= paMax) { printf("Address 0x%llX is out of range\n", address); } -
内存不可访问:某些内存区域可能受到保护,尝试其他地址。
-
设备不支持写入:检查设备是否可写。
QWORD fWritable; LcGetOption(hLC, LC_OPT_CORE_READONLY, &fWritable); if (fWritable) { printf("Device is read-only\n"); } -
缓冲区大小不足:确保提供足够大的缓冲区。
5.3 性能优化建议
-
使用分散读写:对于多个不连续内存块的访问,使用LcReadScatter和LcWriteScatter代替多次LcRead/LcWrite。
-
调整缓冲区大小:根据设备特性调整缓冲区大小,通常较大的缓冲区效率更高,但不要超过设备支持的最大传输大小。
-
减少不必要的刷新:如果不需要实时数据,可以减少缓存刷新频率。
VMMDLL_ConfigSet(hVMM, VMMDLL_OPT_CONFIG_READCACHE_TICKS, 10); // 增加缓存有效期 -
合理设置详细程度:在性能关键场景中,降低输出详细程度。
LcSetOption(hLC, LC_OPT_CORE_PRINTF_ENABLE, 0); // 禁用输出
6. 总结
PCILeech提供了强大的DMA内存访问能力,其核心API包括LeechCore和VMMDLL两个模块。LeechCore提供底层硬件访问,而VMMDLL则提供更高层次的系统分析功能。
本文详细介绍了这两个模块的主要API函数,包括设备初始化、内存读写、配置管理和虚拟文件系统访问等功能,并提供了实用的代码示例。开发者可以基于这些API构建各种DMA应用,如内存取证工具、远程文件浏览器、系统监控工具等。
使用PCILeech API时,应注意以下几点:
- 始终检查函数返回值,妥善处理错误情况
- 根据具体硬件设备特性调整参数,以获得最佳性能
- 在处理敏感操作时,确保有适当的权限和授权
- 注意内存安全,避免缓冲区溢出等问题
通过掌握这些API,开发者可以充分利用PCILeech的强大功能,构建高效、可靠的DMA应用程序。
7. 参考资料
- PCILeech GitHub仓库: https://gitcode.com/gh_mirrors/pc/pcileech
- LeechCore文档: 包含在leechcore.h头文件中
- VMMDLL文档: 包含在vmmdll.h头文件中
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



