从用户模式访问内核内存(Windows)

亚历克斯

我正在编写一个驱动程序,该驱动程序需要分配一个非分页的内存池,并且出于性能考虑,必须可以直接从用户模式程序访问该内存。

在驱动程序条目中,我使用以下两种方法分配了一些内存:

pMdl = IoAllocateMdl(NULL,
                     4096,
                     FALSE,
                     FALSE,
                     NULL);
if(!pMdl) {
    DbgPrintEx(DPFLTR_IHVVIDEO_ID, DPFLTR_INFO_LEVEL, "Error on IoAllocateMdl. Returning from driver early.\n");
    return STATUS_INSUFFICIENT_RESOURCES;
}
MmBuildMdlForNonPagedPool(pMdl);
userMemory = (void *)MmMapLockedPagesSpecifyCache(pMdl, UserMode, MmWriteCombined, NULL, FALSE, LowPagePriority);

userMemory = ExAllocatePoolWithTag(
                NonPagedPool,
                4096,
                POOL_TAG);

现在,我不想每次需要从此内存中进行写入/读取时都发出DeviceIoControl,但是我想做这样的事情:

char* sharedMem;
.....
transactionResult = DeviceIoControl ( hDevice,
                        (DWORD) IOCTL_MMAP,
                        NULL,
                        0,
                        sharedMem,
                        sizeof(int),
                        &bRetur,
                        NULL
                        );
.....
sharedMem[0]='c';

使用DeviceIoControl获取内核内存中的地址,然后直接使用它,就像Linux下的mmap一样。

在Windows中有某种方法可以做到这一点吗?

我已经做到了:

hMapFile = OpenFileMapping(
                FILE_MAP_ALL_ACCESS,     // Read/write access
                TRUE,
                "Global\\SharedMemory"); // Name of mapping object

lastError = GetLastError();
if (hMapFile == NULL)
{
    printf("Could not create file mapping object (%d).\n" ,GetLastError());
    return 1;
}
pBuf = (char*)MapViewOfFile(hMapFile,            // Handle to map object
                            FILE_MAP_ALL_ACCESS, // Read/write permission
                            0,
                            0,
                            4096);

if (pBuf == NULL)
{
    printf("Could not map view of file (%d).\n", GetLastError());
    CloseHandle(hMapFile);
    return 1;
}
pBuf[0] = 'c';
pBuf[1] = '\n';
CloseHandle(hMapFile);

我已经在内核中创建了这样的视图:

RtlInitUnicodeString(&name, L"\\BaseNamedObjects\\SharedMemory");
InitializeObjectAttributes(&oa, &name, 0, 0, NULL);
ZwCreateSection(&hsection, SECTION_ALL_ACCESS, &oa, &Li, PAGE_READWRITE, SEC_COMMIT, NULL);

ZwMapViewOfSection(hsection, NtCurrentProcess(),
                   &userMem, 0, MEM_WIDTH, NULL,
                   &j, ViewShare, 0, PAGE_READWRITE);

但是在内核中,当我读取内存时,它是空的:怎么可能呢?

亚历克斯

我终于明白了这是如何工作的。

首先,我创建了如下结构。

typedef struct _MEMORY_ENTRY
{
    PVOID pBuffer;
} MEMORY_ENTRY, *PMEMORY_ENTRY;

这将用于将虚拟地址从内核空间返回到用户空间。

在我使用的DriverEntry中

userMem = ExAllocatePoolWithTag(NonPagedPool,
                                MEM_WIDTH,
                                POOL_TAG );

设置非页面内存。

然后,我创建了一个在DIRECT_OUT模式下工作的IOCTL,它执行以下代码片段:

...
PMDL         mdl = NULL;
PVOID        buffer = NULL;
MEMORY_ENTRY returnedValue;
 void*       UserVirtualAddress = NULL;
...
buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); // Gets safely the pointer for the output in the IRP
mdl = IoAllocateMdl(userMem, MEM_WIDTH, FALSE, FALSE, NULL); // Allocate the memory descriptor list
MmBuildMdlForNonPagedPool(mdl); // This is needed when we're managing NonPaged memory
UserVirtualAddress = MmMapLockedPagesSpecifyCache(
                         mdl,
                         UserMode,
                         MmNonCached,
                         NULL,
                         FALSE,
                         NormalPagePriority); // Return the virtual address in the context of
                                              // the user space program who called the IOCTL

returnedValue.pBuffer = UserVirtualAddress;
RtlCopyMemory(buffer,
            &returnedValue,
            sizeof(PVOID)); // I copy the virtual address in the structure that will
                            // be returned to the user mode program by the IRP

在用户模式程序中,我只需要这样做

transactionResult = DeviceIoControl(
                        hDevice,
                        (DWORD) IOCTL_MMAP,
                        NULL,
                        0,
                        sharedMem,
                        sizeof(void*),
                        &bRetur,
                        NULL
                        );

在(MEMORY_ENTRY *)sharedMem-> pBuffer中,我们将找到由内核空间创建和共享的内存区域,内核空间可直接由用户程序访问。

我没有写过,但是我们需要记住将整个MmGetSystemAddressForMdlSafe(...)-----> RtlCopyMemory(...)包装在Try ... Except块中,因为我们在这里可能会遇到各种问题最终会导致BugCheck,因此比后悔更安全。无论如何,如果您在检查的环境中编译此类代码,Microsoft AutocodeReview将指出这一点。

如果有人需要更多说明,或者我写错了什么,请告诉我,我很乐意修改这篇文章。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

从用户模式访问内核内存(Windows)

来自分类Dev

访问内核模式驱动程序内的用户模式内存

来自分类Dev

访问内核模式驱动程序中的用户模式内存

来自分类Dev

关于从内核访问用户空间内存

来自分类Dev

Windows虚拟内存和内核模式

来自分类Dev

内核和用户模式之间的共享内存。如何分享句柄?

来自分类Dev

用户程序的内核模式

来自分类Dev

内核模式-通过共享内存进行用户模式通信,而无需使用系统线程

来自分类Dev

内核模块内存访问

来自分类Dev

内核模块内存访问

来自分类Dev

在没有驱动程序的情况下从用户模式读取内核内存

来自分类Dev

Windows CE:在用户模式下映射物理内存

来自分类Dev

内核和用户模式的区别

来自分类Dev

为什么Windows NT线程具有单独的用户模式/内核模式堆栈?

来自分类Dev

Windows Server调试:在WDM内核模式驱动程序断点中查看用户模式堆栈

来自分类Dev

从用户模式切换到内核模式

来自分类Dev

从用户模式切换到内核模式

来自分类Dev

从用户模式转移到内核模式

来自分类Dev

在Windows 7下如何在内核模式下设置内存区域的保护

来自分类Dev

分配内存-内核模式(OS X)

来自分类Dev

内存布局和内核空间-用户空间

来自分类Dev

MySQL进程是否以用户或内核模式运行?

来自分类Dev

PCI硬件访问速度-内核与用户空间

来自分类Dev

printf是在内核模式还是用户模式下运行?

来自分类Dev

“内核模式”和“用户模式”是硬件功能还是软件功能?

来自分类Dev

CIFS 驱动程序是用户模式还是内核模式?

来自分类Dev

什么代码是用户模式代码,什么代码是内核模式代码?

来自分类Dev

如何通过内存映射从Linux内核空间访问PCI内存(内核3.14)

来自分类Dev

如何通过内存映射从Linux内核空间访问PCI内存(内核3.14)

Related 相关文章

  1. 1

    从用户模式访问内核内存(Windows)

  2. 2

    访问内核模式驱动程序内的用户模式内存

  3. 3

    访问内核模式驱动程序中的用户模式内存

  4. 4

    关于从内核访问用户空间内存

  5. 5

    Windows虚拟内存和内核模式

  6. 6

    内核和用户模式之间的共享内存。如何分享句柄?

  7. 7

    用户程序的内核模式

  8. 8

    内核模式-通过共享内存进行用户模式通信,而无需使用系统线程

  9. 9

    内核模块内存访问

  10. 10

    内核模块内存访问

  11. 11

    在没有驱动程序的情况下从用户模式读取内核内存

  12. 12

    Windows CE:在用户模式下映射物理内存

  13. 13

    内核和用户模式的区别

  14. 14

    为什么Windows NT线程具有单独的用户模式/内核模式堆栈?

  15. 15

    Windows Server调试:在WDM内核模式驱动程序断点中查看用户模式堆栈

  16. 16

    从用户模式切换到内核模式

  17. 17

    从用户模式切换到内核模式

  18. 18

    从用户模式转移到内核模式

  19. 19

    在Windows 7下如何在内核模式下设置内存区域的保护

  20. 20

    分配内存-内核模式(OS X)

  21. 21

    内存布局和内核空间-用户空间

  22. 22

    MySQL进程是否以用户或内核模式运行?

  23. 23

    PCI硬件访问速度-内核与用户空间

  24. 24

    printf是在内核模式还是用户模式下运行?

  25. 25

    “内核模式”和“用户模式”是硬件功能还是软件功能?

  26. 26

    CIFS 驱动程序是用户模式还是内核模式?

  27. 27

    什么代码是用户模式代码,什么代码是内核模式代码?

  28. 28

    如何通过内存映射从Linux内核空间访问PCI内存(内核3.14)

  29. 29

    如何通过内存映射从Linux内核空间访问PCI内存(内核3.14)

热门标签

归档