本文主要是介绍滴水中级班保护模式阶段测试作业,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
// 保护模式阶段测试第一题.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;
}
这篇关于滴水中级班保护模式阶段测试作业的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!