保护模式阶段测试

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

练习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 @ 2022-02-25 12:55  zpchcbd  阅读(244)  评论(0)    收藏  举报