保护模式阶段测试

前言:保护模式的阶段测试,作为保护模式章节的结束,对所学的知识的测试,这篇作为保护模式阶段测试的记录

练习1

实现给定一个线性地址,和长度,读取内容

int ReadMemory(OUT BYTE* buffer,IN DWORD dwAddr,IN DWORD dwLeght)

要求:

  • 可以自己指定分页方式。
  • 页不存在,要提示,不能报错。
  • 可以正确读取数据。

因为自己想用汇编写,但是有点吃力,所以我这里就只实现读取4个字节了,对于跨页的情况是有考虑的,并且已经写进去了,代码如下

#include<windows.h>
#include<stdio.h>
#include<stdlib.h>
DWORD g_dwRet=0;
DWORD g_dwAddr;
DWORD g_dwLength;
DWORD* g_pBuffer;
__declspec(naked) void readFunc()
{
__asm
{
pushad;
pushfd;
mov ecx, g_dwAddr;
mov eax, ecx;
shr eax, 14h;
mov edx, 0FFCh;
and eax, edx;
sub eax, 3FD00000h; // eax = PDE's addr;
mov eax, [eax]; // eax = PDE's value;
test al, 1; // p bit isValid
jz _fail;
shr ecx, 0Ah;
and ecx, 3FFFFCh;
sub ecx, 40000000h;
mov eax, ecx; // eax = PTE's addr;
mov ecx, [eax]; // eax = PTE's value;
test cl, 1;
jz _fail;
mov eax, g_dwAddr;
and eax, 00000FFFh;
mov ebx, 00001000h;
sub ebx, eax;
mov ecx, g_dwLength; // g_dwLength = 4
sub ebx, ecx; // ecx=4 -> cmp ebx, 4;
js _second;
//////
mov ebx, dword ptr ds:[g_dwAddr];
mov dword ptr ds:[g_pBuffer], ebx;
jmp _success;
_second:
add ebx, ecx;
sub ecx, ebx;
push ecx;
mov ecx, g_dwAddr;
and ecx, 0xFFFFF000;
add ecx, 0x1000;
//////////
mov eax, ecx;
shr eax, 14h;
mov edx, 0FFCh;
and eax, edx;
sub eax, 3FD00000h; // eax = PDE's addr;
mov eax, [eax]; // eax = PDE's value;
test al, 1; // p bit isValid
jz _fail;
shr ecx, 0Ah;
and ecx, 3FFFFCh;
sub ecx, 40000000h;
mov eax, ecx; // eax = PTE's addr;
mov ecx, [eax]; // eax = PTE's value;
test cl, 1;
jz _fail;
xor ecx,ecx;
pop ecx;
_loopRead:
dec ecx;
test ecx,ecx;
jnz _loopRead;
mov ebx, dword ptr ds:[g_dwAddr];
mov dword ptr ds:[g_pBuffer], ebx;
jmp _success;
_success:
mov g_dwRet, 1;
jmp _end;
_fail:
mov g_dwRet, 0;
jmp _end;
_end:
popfd;
popad;
iretd;
}
}
DWORD ReadMemory(DWORD* buffer, DWORD dwAddr, DWORD dwLength)
{
g_pBuffer = buffer;
g_dwAddr = dwAddr;
g_dwLength = dwLength;
__asm
{
int 0x20;
}
return 0;
}
int main()
{
//eq 8003f500 0040EE00`0008100A
DWORD dwBuffer;
DWORD dwAddr = (DWORD)VirtualAlloc(NULL, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if(dwAddr == 0)
{
printf("virtualAlloc Failed!\n");
system("pause");
return 0;
}
memset((DWORD*)dwAddr, 0, 0x1000);
*(DWORD*)dwAddr = 0x12345678;
printf("virtualAlloc: %x\n", dwAddr);
printf("readFunc: %x\n", readFunc);
ReadMemory(&dwBuffer, dwAddr, 4);
printf("g_dwRet: %x\n", g_dwRet);
if(g_dwRet)
{
printf("ReadMemory successed\n");
printf("ReadMemory content: %x", *g_pBuffer);
}else
printf("ReadMemory failed\n");
VirtualFree((DWORD*)dwAddr, 0x1000, MEM_COMMIT | MEM_RESERVE);
system("pause");
return 0;
}

练习2

申请长度为100的DWORD的数组,且每项用该项的地址初始化;

把这个数组所在的物理页挂到0x1000的地址上;

定义一个指针,指向0x1000这个页里的数组所在的地址,用0x1000这个页的线性地址打印出这数组的值;

要求:

  • 数组所在的物理页,是同一个页;
#include<windows.h>
#include<stdio.h>
#include<stdlib.h>
DWORD g_dwRet=0;
DWORD g_dwAddr;
DWORD g_dwLength;
DWORD g_value;
DWORD* getPDE(DWORD addr)
{
DWORD PDI = addr>>22;
DWORD PTI = (addr>>12) & 0x000003FF;
return (DWORD*)(0xC0300000 + PDI * 4);
}
DWORD* getPTE(DWORD addr)
{
DWORD PDI = addr>>22;
DWORD PTI = (addr>>12)&0x000003FF;
return (DWORD*)(0xC0000000 + PDI * 0x1000 + PTI * 4);
}
__declspec(naked) void readFunc()
{
__asm
{
push ebp;
mov ebp, esp;
sub esp,0x1000;
pushad;
pushfd;
push fs;
}
*getPDE(0x1000) = *getPDE(g_dwAddr);
*getPTE(0x1000) = *getPTE(g_dwAddr);
__asm
{
//int 3;
pop fs;
popfd;
popad;
add esp,0x1000;
mov esp,ebp;
pop ebp;
iretd;
}
/*
__asm
{
pushad;
pushfd;
mov ecx, 0x1000;
mov eax, ecx;
shr eax, 14h;
mov edx, 0FFCh;
and eax, edx;
sub eax, 3FD00000h; // eax = PDE's addr;
mov ebx, dword ptr ds:[eax]; // eax = PDE's value;
and ebx, 0xFFFFF0FF;
mov dword ptr ds:[eax], ebx;
mov ecx, g_dwAddr;
shr ecx, 0Ah;
and ecx, 3FFFFCh;
sub ecx, 40000000h;
mov eax, ecx;
mov ecx, [eax];
and ecx, 0xFFFFF0FF;// ecx = g_dwAddr's content;
mov edx, 0x1000;
shr edx, 0Ah;
and edx, 3FFFFCh;
sub edx, 40000000h;
mov dword ptr ds:[edx], ecx;
_end:
popfd;
popad;
iretd;
}*/
}
int main()
{
//eq 8003f500 0040EE00`0008100A
DWORD i;
DWORD dwAddr = (DWORD)VirtualAlloc(NULL, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if(!dwAddr)
{
printf("virtualAlloc Failed!\n");
system("pause");
return -1;
}
memset((DWORD*)dwAddr, 0, 0x1000);
printf("virtualAlloc: %x\n", dwAddr);
g_dwAddr = dwAddr;
for(i=0;i<100;i++)
{
*((DWORD*)dwAddr+i) = (DWORD)((DWORD*)dwAddr+i);
}
__asm
{
int 0x20;
}
for(i=0;i<100;i++)
{
printf("%d\n", *(DWORD*)(0x1000+i*4));
}
VirtualFree((DWORD*)dwAddr, 0x1000, MEM_COMMIT | MEM_RESERVE);
system("pause");
return 0;
}

posted @   zpchcbd  阅读(177)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示