WDF 驱动程序开发的简单演示






4.78/5 (7投票s)
在用户模式下访问物理内存和I/O端口
引言
WINFO是一款互联网上广为人知的工具,可以直接访问I/O和内存。它应用了微软未公开的函数(NATIVE API)来获取I/O数据。PCI View的设计结构基于WDF,旨在模拟WINFO的功能,以访问I/O和内存。
背景
需要具备Win32 SDK的知识。
程序结构

PCI View可以通过IOMEM.DLL或DeviceIoControl
或ReadFile
/WriteFile
函数访问I/O端口和内存。
应用程序介绍
在Windows NT环境下,可以使用READ_PORT_UCHAR(USHORT/ULONG)
或WRITE_PORT_UCHAR(USHORT/ULONG)
API函数访问I/O端口。这些API函数的使用方式类似于C语言运行时库提供的函数,例如_outp
和_inp
。
case 1: //UCHAR
if (pvInputBuffer->Command == 0) //decide to write or read
WRITE_PORT_UCHAR((PUCHAR)pvInputBuffer->PortBase, (UCHAR)pvInputBuffer->Data);
else
*(PUCHAR)pvOutputBuffer = READ_PORT_UCHAR((PUCHAR)pvInputBuffer->PortBase);
break;
case 2: // USHORT
if (pvInputBuffer->Command == 0)
WRITE_PORT_USHORT((PUSHORT)pvInputBuffer->PortBase, (USHORT)pvInputBuffer->Data);
else
*(PUSHORT)pvOutputBuffer = READ_PORT_USHORT((PUSHORT)pvInputBuffer->PortBase);
break;
case 4: //ULONG
if (pvInputBuffer->Command == 0)
WRITE_PORT_ULONG((PULONG)pvInputBuffer->PortBase, (ULONG)pvInputBuffer->Data);
else
*(PULONG)pvOutputBuffer = READ_PORT_ULONG((PULONG)pvInputBuffer->PortBase);
break;
内存处理比I/O处理更复杂,而I/O处理可以通过API函数轻松完成。
- 首先,我们需要获取用户想要访问内存的地址和长度。然后,
MmMapIoSpace
函数可以将地址和长度映射到非分页系统空间。 - 如果之前的过程成功,那么分配
IoAllocateMdland MmBuildMdlForNonPagedPool
就足以缓冲以映射实际内存。 MmMapLockedPagesSpecifyCache
函数可以将虚拟内存映射到调用者。因此,RING 3应用程序可以直接获取内存。
//Step 1.
memReq.MapIo = MmMapIoSpace(Address, memReq.Length, MmNonCached);
if (memReq.MapIo == NULL)
{
status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
};
// Step 2.
memReq.Mdl = IoAllocateMdl(memReq.MapIo, memReq.Length, FALSE, FALSE, NULL);
if (memReq.Mdl == NULL)
{
status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
};
MmBuildMdlForNonPagedPool(memReq.Mdl);
// Step 3.
memReq.Buffer = (PUCHAR)MmMapLockedPagesSpecifyCache(memReq.Mdl,
UserMode, //set value as UserMode
MmNonCached,
NULL,
FALSE,
NormalPagePriority);
if (memReq.Buffer == NULL)
{
status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
};
实模式下的动态函数提供了outp
、_outpw
、_outpd
、_inp
、_inpw
和_inpd
来访问I/O端口。有四个函数,例如MapMemory
、UnmapMemory
、ReadPhyicalMemory
和WritePhyicalMemory
,可用于获取内存。
函数:设计用于访问内存的地址和长度
PUCHAR MapMemory(__in ULONG Address, __in ULONG Length);
Address : To access the beginning address of memory.
Length : To get the length of memory
The function will return the beginning address mapping in memory
when executed successfully.
Function: Release the assigned memory.
BOOLEAN UnmapMemory(VOID);
示例程序
该应用程序提供了一个访问IO-MEM的示例。在不包含DLL包的情况下,该应用程序在直接调用IOMEM.DLL时显示分配的内存或I/O端口的信息。可以从http://bbs.codeheaven.com.tw/下载源代码。

示例

历史
- 2010年4月26日:初始发布