您的位置:首页 > 其它

关于MDL的一些事情

2013-06-27 12:10 501 查看


关于MDL的一些事情(未完)

(2011-05-25 18:26:30)


转载▼

标签:


it

分类: 驱动/内核
微软的文档里对MDL的描述感觉语焉不详,这两天在找工作的间隙逆向+黑盒测试了一下MmBuildMdlForNonPagedPool,把得到的一些理解描述下来。

一.MDL数据结构

MDL是用来建立一块虚拟地址空间与物理页面之间的映射,结构定义如下:

view plaincopy to clipboardprint?

typedef struct _MDL {

struct _MDL *Next;

CSHORT Size;

CSHORT MdlFlags;

struct _EPROCESS *Process;

PVOID MappedSystemVa; //StartVa+ByteOffset

PVOID StartVa; //页开始地址 4k对齐

ULONG ByteCount;

ULONG ByteOffset;

} MDL, *PMDL;

typedef struct _MDL {

struct _MDL *Next;

CSHORT Size;

CSHORT MdlFlags;

struct _EPROCESS *Process;

PVOID MappedSystemVa;

PVOID StartVa;

ULONG ByteCount;

ULONG ByteOffset;

} MDL, *PMDL;

各field的解释:

Next:MDL可以连接成一个单链表,这在IRP的结构里能找到。具体是做什么用的参考对IRP的描述

Size:一个MDL并不单单包含结构里这些东西,在内存中紧接着一个MDL结构,存着这个MDL对应的各个物理页面编号,由于一个物理页面一定是4KB对齐的,所以这个编号相当于一个物理页面起始地址的高20位。Size的值减去sizeof(MDL),等于存放编号的区域的大小。比如该MDL需要三个物理页面来映射虚拟地址空间,则Size-sizeof(MDL)==4*3==12;

MdlFlags:与这个MDL相关的一些标记

Process:如果虚拟地址是某一进程的用户地址空间,那么MDL代表的这块虚拟地址必须是从属于某一个进程,这个成员指向从属进程的结构

MappedSystemVa:该MDL结构对应的物理页面可能被映射到内核地址空间,这个成员代表这个内核地址空间下的虚拟地址。对MmBuildMdlForNonPagedPool的逆向表明,MappedSystemVa=StartVa+ByteOffset。这是因为这个函数的输入MDL,其StartVa是由ExAllocatePoolWithTag决定的,所以已经从内核空间到物理页面建立了映射,MappedSystemVa自然就可以这样算。 可以猜测,如果是调用MmProbeAndLockPages
返回,则MappedSystemVa不会与StartVa有这样的对应关系,因为此时对应的物理页面还没有被映射到内核空间。(此处未定,MmProbeAndLockPages 是否会到PDE与PTE中建立映射,未知。)

StartVa:虚拟地址空间的首地址,当这块虚拟地址描述的是一个用户进程地址空间的一块时,这个地址从属于某一个进程。

ByteCount:虚拟地址块的大小,字节数

ByteOffset:StartVa+ByteCount等于缓冲区的开始地址

二.对MmBuildMdlForNonPagedPool的黑盒测试

测试的程序主要执行如下步骤:

1.用 ExAllocatePoolWithTag在内核地址空间的NonpagedPool分配一块10000自己的区域

2.用上述得到的地址和大小调用IoAllocateMdl,返回一个MDL

3.打印该MDL个成员的值

4.调用MmBuildMdlForNonPagedPool

5.打印MDL各成员的值,比较与步骤3中的不同

代码如下:

view plaincopy to clipboardprint?

#include "ntddk.h"

#include "wdm.h"

#include "ntdef.h"

#define BUF_LENGTH 10000

static void OutputMDL(PMDL pMDL);

static void Unload( IN PDRIVER_OBJECT pDriverObject);

NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegistryPath )

{

PVOID pBuf = NULL;

PMDL pMDL;

//set up unload routing

pDriverObject->DriverUnload = Unload;

//allocate memory from non-paged pool

pBuf = ExAllocatePoolWithTag(NonPagedPool,BUF_LENGTH,(ULONG)DriverEntry);

if(!pBuf) {

DbgPrint("ExAllocatePoolWithTag failed.\n");

return STATUS_SUCCESS;

}

DbgPrint("MDL_TEST: pBuf=0xx\n",(ULONG)pBuf);

//allocate a MDL

pMDL = IoAllocateMdl(pBuf,BUF_LENGTH,FALSE,FALSE,NULL);

if(!pMDL) {

DbgPrint("IoAllocateMdl failed.\n");

ExFreePoolWithTag(pBuf,(ULONG)DriverEntry);

return STATUS_SUCCESS;

}

//print MDL right after IoAllocateMdl

OutputMDL(pMDL);

//

DbgPrint("****************************************\n");

//call MmBuildMdlForNonPagedPool

MmBuildMdlForNonPagedPool(pMDL);

//print MDL after MmBuildMdlForNonPagedPool is called

OutputMDL(pMDL);

//return

IoFreeMdl(pMDL);

ExFreePoolWithTag(pBuf,(ULONG)DriverEntry);

return STATUS_SUCCESS;

}

void Unload( IN PDRIVER_OBJECT pDriverObject)

{

DbgPrint("MDL_TEST: Unloading. 88\n");

}

void OutputMDL(PMDL pMDL)

{

int i;

ULONG * p = (ULONG*)(pMDL+1);

DbgPrint("MDL_TEST: Size=%d\n",pMDL->Size);

DbgPrint("MDL_TEST: MdlFlags=0xx\n",pMDL->MdlFlags);

DbgPrint("MDL_TEST: Process=0xx\n",(ULONG)pMDL->Process);

DbgPrint("MDL_TEST: MappedSystemVa=0xx\n",(ULONG)pMDL->MappedSystemVa);

DbgPrint("MDL_TEST: StartVa=0xx\n",(ULONG)pMDL->StartVa);

DbgPrint("MDL_TEST: ByteCount=%u\n",pMDL->ByteCount);

DbgPrint("MDL_TEST: ByteOffset=%u\n",pMDL->ByteOffset);

//print a few 4-bytes after the MDL structure

for(i=0;i<5;i++)

DbgPrint("MDL_TEST: p[%d]=0xx\n",i,p[i]);

}

#include "ntddk.h"

#include "wdm.h"

#include "ntdef.h"

#define BUF_LENGTH 10000

static void OutputMDL(PMDL pMDL);

static void Unload( IN PDRIVER_OBJECT pDriverObject);

NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegistryPath )

{

PVOID pBuf = NULL;

PMDL pMDL;

//set up unload routing

pDriverObject->DriverUnload = Unload;

//allocate memory from non-paged pool

pBuf = ExAllocatePoolWithTag(NonPagedPool,BUF_LENGTH,(ULONG)DriverEntry);

if(!pBuf) {

DbgPrint("ExAllocatePoolWithTag failed.\n");

return STATUS_SUCCESS;

}

DbgPrint("MDL_TEST: pBuf=0xx\n",(ULONG)pBuf);

//allocate a MDL

pMDL = IoAllocateMdl(pBuf,BUF_LENGTH,FALSE,FALSE,NULL);

if(!pMDL) {

DbgPrint("IoAllocateMdl failed.\n");

ExFreePoolWithTag(pBuf,(ULONG)DriverEntry);

return STATUS_SUCCESS;

}

//print MDL right after IoAllocateMdl

OutputMDL(pMDL);

//

DbgPrint("****************************************\n");

//call MmBuildMdlForNonPagedPool

MmBuildMdlForNonPagedPool(pMDL);

//print MDL after MmBuildMdlForNonPagedPool is called

OutputMDL(pMDL);

//return

IoFreeMdl(pMDL);

ExFreePoolWithTag(pBuf,(ULONG)DriverEntry);

return STATUS_SUCCESS;

}

void Unload( IN PDRIVER_OBJECT pDriverObject)

{

DbgPrint("MDL_TEST: Unloading. 88\n");

}

void OutputMDL(PMDL pMDL)

{

int i;

ULONG * p = (ULONG*)(pMDL+1);

DbgPrint("MDL_TEST: Size=%d\n",pMDL->Size);

DbgPrint("MDL_TEST: MdlFlags=0xx\n",pMDL->MdlFlags);

DbgPrint("MDL_TEST: Process=0xx\n",(ULONG)pMDL->Process);

DbgPrint("MDL_TEST: MappedSystemVa=0xx\n",(ULONG)pMDL->MappedSystemVa);

DbgPrint("MDL_TEST: StartVa=0xx\n",(ULONG)pMDL->StartVa);

DbgPrint("MDL_TEST: ByteCount=%u\n",pMDL->ByteCount);

DbgPrint("MDL_TEST: ByteOffset=%u\n",pMDL->ByteOffset);

//print a few 4-bytes after the MDL structure

for(i=0;i<5;i++)

DbgPrint("MDL_TEST: p[%d]=0xx\n",i,p[i]);

}

执行的结果如下:

view plaincopy to clipboardprint?

MDL_TEST: pBuf=0xadc92000

MDL_TEST: Size=40

MDL_TEST: MdlFlags=0x0008

MDL_TEST: Process=0x87e85c88

MDL_TEST: MappedSystemVa=0x95fb1cc4

MDL_TEST: StartVa=0xadc92000

MDL_TEST: ByteCount=10000

MDL_TEST: ByteOffset=0

MDL_TEST: p[0]=0x0002d72f

MDL_TEST: p[1]=0x0002e2b0

MDL_TEST: p[2]=0x0007e15a

MDL_TEST: p[3]=0x0007e15b

MDL_TEST: p[4]=0x0007e15c

****************************************

MDL_TEST: Size=40

MDL_TEST: MdlFlags=0x000c

MDL_TEST: Process=0x00000000

MDL_TEST: MappedSystemVa=0xadc92000

MDL_TEST: StartVa=0xadc92000

MDL_TEST: ByteCount=10000

MDL_TEST: ByteOffset=0

MDL_TEST: p[0]=0x0005bd23

MDL_TEST: p[1]=0x0005bea2

MDL_TEST: p[2]=0x0005bb21

MDL_TEST: p[3]=0x0007e15b

MDL_TEST: p[4]=0x0007e15c

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Squirrel_Program/archive/2009/11/15/4813674.aspx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: