通过代码挂上物理页

给0地址挂上物理页,吧VirtualAlloc函数开辟的线性地址物理页给0地址挂上,这样这两个线性地址访问的就是同一个物理页,

内存映射的本质就是相同或者不同进程的两个线性地址,使用同一个物理页

这个是2-9-9-12分页的,如果10-10-12分页会更简单,代码可以在此基础上改

这里我将只提几个需要注意到的问题

1.memset填充是为了  VirutalAlloc开辟内存后,线性地址并不会马上挂上物理页,PTE没有指向物理页需要注意

2.那个裸函数注释掉的代码需要注意,虽然说要把那个线性地址PDE和PTE给0挂上,但是0本身有PDE而且一张PTT表(

写可以找到2MB的物理内存)异常  而ring3堆栈 在0x0013XXXX  所以ring3堆栈访问的时候需要依赖0线性地址本身的PDE

一个PDE项可以访问2MB,0-0x00200000  这段线性地址公有一个PDE,所以如果给0地址挂上PDE直接就挂了,(Ring3下)访问堆栈的指令就全都完了,我调试了大半天在才发现这第2个错误需要大家注意

如果想理解PDE和PTE公式计算的本质,或者页机制的本质可以看这篇帖子https://blog.csdn.net/taolaodawho/article/details/109183883,里面详细的描述了页表是如何映射到线性地址的

 

#include "stdafx.h"
#include <Windows.h>
typedef struct AddresSegment{  //这个用于扩展,这里面并没有用到                        
    DWORD PDPI;
    DWORD PDEI;
    DWORD PTEI;
}ADDRESSSEGMENT;

//将目标线性地址开始的一个页,挂到源地址上上
typedef  struct  PageAttrib{
    DWORD  PTELOW;
    DWORD  PTEHIGH;
    DWORD  PDELOW;
    DWORD  PDEHIGH;
    DWORD  SrcAddress;            //源地址线性地址
    DWORD  DestAddress;          //目标线性地址                     
    DWORD  PDESrcAddress;
    DWORD  PTESrctAddress;
    DWORD  PDEDestAddress;
    DWORD  PTEDestAddress;
    ADDRESSSEGMENT  DestSeg;
    ADDRESSSEGMENT  SrcSeg;
}PAGEATTRIB;
PAGEATTRIB  Page;
void  InitAddress(){
   Page.DestAddress=0x10000000;
   Page.SrcAddress=0x0;

   Page.DestSeg.PDPI =((Page.DestAddress&0xC0000000)>>30);
   Page.DestSeg.PDEI =((Page.DestAddress&0x3FE00000)>>21);                //0011  1111  1110
   Page.DestSeg.PTEI =((Page.DestAddress&0x001FF000)>>12);
    
   Page.SrcSeg.PDPI  =((Page.SrcAddress&0xC0000000)>>30);
   Page.SrcSeg.PDEI  =((Page.SrcAddress&0x3FE00000)>>21);    
   Page.SrcSeg.PTEI  =((Page.SrcAddress&0x001FF000)>>12);    

   Page.PDESrcAddress =0xC0600000+((Page.SrcAddress>>18)&0x3FF8);  
   Page.PTESrctAddress=0xC0000000+((Page.SrcAddress>>9)&0x7ffff8);

   Page.PDEDestAddress=0xC0600000+((Page.DestAddress>>18)&0x3FF8);
   Page.PTEDestAddress=0xC0000000+((Page.DestAddress>>9)&0x7ffff8);
 
  
}
void  _declspec(naked) print(){
    __asm{
    
         pushad
         pushfd
         mov eax,dword ptr ds:[Page.PDEDestAddress]
         mov ecx,dword ptr ds:[Page.PTEDestAddress]
         mov ebx,[eax]
         mov edx,[eax+4]
         mov dword ptr ds:[Page.PDELOW],ebx
         mov dword ptr ds:[Page.PDEHIGH],edx        //获得目标 物理页  PDE
        
         mov ebx,[ecx]
         mov edx,[ecx+4]
         mov dword ptr ds:[Page.PTELOW],ebx
         mov dword ptr ds:[Page.PTEHIGH],edx

#if 0
         mov eax,Page.PDELOW
         mov ecx,Page.PDEHIGH
         mov edx,Page.PDESrcAddress
         mov dword ptr ds:[edx],eax
         mov dword ptr ds:[edx+4],ecx
#endif   

         mov eax,Page.PTELOW
         mov ecx,Page.PTEHIGH
         mov edx,Page.PTESrctAddress
          mov dword ptr ds:[edx],eax
         mov dword ptr ds:[edx+4],ecx

         popfd
         popad
         retf

    }
}
int main(int argc, char* argv[])
{
    char buf[6];
    char* Addr=(char*)VirtualAlloc((void*)0x10000000,0x1000,MEM_RESERVE | MEM_COMMIT,PAGE_READWRITE);
    if(NULL==Addr){
        MessageBox(0,0,"开辟内存失败",0);
    }
    memset(Addr,0x66,0x1000);
    *(WORD*)&buf[4]=0x48;
    InitAddress();
    printf("Address=%p\n",print);
    
    __asm{
        call  fword ptr buf;
        mov   ax,0x3b
        mov   fs,ax
    }


    int* p=NULL;
    *p=0x1231435;

    
    printf("Hello World!\n");
    return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值