通過程式碼掛上物理頁

伴你永居我憶i發表於2020-10-28

給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直接就掛了,訪問堆疊的指令就全都完了,我除錯了大半天在才發現這第2個錯誤需要大家注意

#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;
}

 

相關文章