滴水中級班保護模式階段測試作業

伴你永居我憶i發表於2020-11-08

// 保護模式階段測試第一題.cpp : Defines the entry point for the console application.
//

1給定一個線性地址,長度,讀取內容

2-9-9-12

#include "stdafx.h"
#include <Windows.h>
typedef struct PAGE{
    DWORD PTELinkAddress;
    DWORD PDELinkAddress;
    DWORD PTELow;
    DWORD PDELow;
};
char Buf[6];
PAGE Page;    
void  _declspec(naked) print(){
    __asm{

        pushad
        pushf
        mov  eax,dword ptr ds:[Page.PTELinkAddress]
        mov  eax,dword ptr ds:[eax]
        mov  dword ptr ds:[Page.PTELow],eax
        mov  eax,dword ptr ds:[Page.PDELinkAddress]
        mov  eax,dword ptr ds:[eax]
        mov  dword ptr ds:[Page.PDELow],eax
        popf
        popad
        retf
    }
}
void Init(int LinkAddress){

    Page.PDELinkAddress=0xC0600000+((LinkAddress>>18)&0x3ff8);
    Page.PTELinkAddress=0xC0000000+((LinkAddress>>9)&0x7ffff8);
}
int MmIsAddressValid(int LinkAddress){
    Init(LinkAddress);
    __asm{
        call fword ptr Buf;
    }
    if(0==Page.PDELow&0x1){    //PDE p位為1PTT無效
        return 0;
    }
    if(0==Page.PTELow*0x1){    //PTE p位為1物理頁無效
        return 0;
    }
    return true;
}
int ReadMemory(void* SrcAddress,DWORD DestAddresss,DWORD size){
    int cout=((int)DestAddresss)%0x1000;
    if(cout+size<=0x1000){                //訪問的資料在一個物理頁
        if(0==MmIsAddressValid(((int)DestAddresss)&0xfffff000)){
            return 0;
        }
        memcpy(SrcAddress,(void*)DestAddresss,size);
    }
    else{                                //訪問的資料長度不在一個物理頁上
        int n=(cout+size)/0x1000+1;        //需要訪問這麼多個頁才能知道有沒有記憶體能不能讀
        int RoundAddress=(((int)DestAddresss)&0xfffff000);
        for(int i=0;i<n;i++){
            if(0==MmIsAddressValid(((int)RoundAddress))){
                return 0;                //只要有一個頁沒有掛物理頁就返回失敗
            }
            RoundAddress+=0x1000;
        }
        memcpy(SrcAddress,(void*)DestAddresss,size);
    }
    return 1;
}
int main(int argc, char* argv[])
{
    int* P=(int*)VirtualAlloc(NULL,0x1000,MEM_RESERVE | MEM_COMMIT,PAGE_READWRITE);
    *((WORD*)&Buf[4])=0x48;
    printf("%p\n",print);
    if(0==ReadMemory((void*)P,0x300000,0x1000)){
        MessageBox(0,0,"讀取記憶體失敗",0);
    }

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

 

保護模式階段測試第二題

#include "stdafx.h"
#include <Windows.h>
#define  SRCADDRESS   0x1000
typedef struct PAGE{
    DWORD SrcLinkAddress;
    DWORD DestLinkAddress;        //把目標地址線性的物理頁掛到原線性地址的屋裡也出
    DWORD DestPDELinkAddress;
    DWORD DestPTELinkAddress;
    DWORD SrcPDELinkAddress;
    DWORD SrcPTELinkAddress;
};
PAGE Page;
void Init(int* P){
    Page.SrcLinkAddress=SRCADDRESS;
    Page.DestLinkAddress=(int)P;
    int a=(((Page.DestLinkAddress)>>18)&0x3ff8);
    Page.DestPDELinkAddress=0xC0600000+((Page.DestLinkAddress>>18)&0x3ff8);
    Page.DestPTELinkAddress=0xC0000000+((Page.DestLinkAddress>>9)&0x7ffff8);
    Page.SrcPDELinkAddress=0xC0600000+((Page.SrcLinkAddress>>18)&0x3ff8);
    Page.SrcPTELinkAddress=0xC0000000+((0x1000>>9)&0x7ffff8);
}//0001 000 0 0000 0000
 
void  _declspec(naked) print(){
    __asm{
    
        pushad
        mov edx,dword ptr ds:[Page.SrcPDELinkAddress]        //原地址PDE的p位  判斷是否有
        and edx,0x1
        jne  taolaod                                        //P位不等於0

        //如果把0x1000的PDE了會改變 2MB線性地址的物理頁全都錯亂
        //如果VirtualAlloc分配的地址是上下有2GB線性地址沒有掛需要給src的線性地址掛上PTE
        //這裡面是給0x1000線性地址如果該PDE堆疊就掛了 ring3堆疊就掛了  0x1000線性地址與ring3堆疊公有一個PTE,我曾經吃過虧
taolaod:
        mov eax,dword ptr ds:[Page.DestPTELinkAddress]
        mov ecx,dword ptr ds:[eax]
        mov eax,dword ptr ds:[eax+4]

        mov edx,ds:[Page.SrcPTELinkAddress]
        mov dword ptr ds:[edx],ecx
        mov dword ptr ds:[edx+4],eax
        popad
        retf
    }
}
int main(int argc, char* argv[])
{
    int  i=0;
    char Buf[6];
    int* P=(int*)VirtualAlloc(NULL,0x1000,MEM_RESERVE | MEM_COMMIT,PAGE_READWRITE);
    if(NULL==P){
        MessageBox(NULL,0,"VirtualAlloc開闢記憶體失敗",0);
    }
    for(i=0;i<100;i++){
        P[i]=(int)(P+i);
    }
    Init(P);
    *((WORD*)&Buf[4])=0x48;
    printf("%p\n",print);
    int c=0;
    __asm{
        call fword ptr Buf;
    }
    int *a=(int*)0x1000;
    for(i=0;i<100;i++){
        if(i%5){
            printf("%p\t",a[i]);
        }else{
            printf("\n");
        }
    }
    printf("Hello World!\n");
    return 0;
}
 

相關文章