保护模式阶段测试
前言:保护模式的阶段测试,作为保护模式章节的结束,对所学的知识的测试,这篇作为保护模式阶段测试的记录
练习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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY