滴水中级班保护模式阶段测试作业

// 保护模式阶段测试第一题.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;
}