www.pudn.com > HookAPI > Ring0.cpp


#include  
#include "ring0.h" 
 
#ifdef WIN95 
//DWORD g_result =0, g_eax =0; 
// 修改地址属性 
__declspec(naked) void Ring0ModifyPageProtection() 
{ 
	_asm 
	{ 
	//Mov [g_result], 1  
		Mov EAX, ECX 
		Shr EAX, 22 
		Test DWORD PTR [0FFBFE000h + EAX * 4], 1 
		Jz Fail 
 
 	//Mov [g_result], 2  
		Mov EAX, ECX 
		Shr EAX, 12 
		Mov EBX, EAX 
		Mov EAX, DWORD PTR [0FF800000h + EAX * 4] 
		Test EAX, 1 
		//Jz Fail	// changed by Paladin 2003.01.23 
 
	//Mov [g_result], 3 // 
 
		Mov EAX, 1 
		Cmp EDX, PAGE_READWRITE 
		Je PageReadWrite 
 
		And DWORD PTR [0FF800000h + EBX * 4], 0xFFFFFFFD 
		Jmp Done 
 
PageReadWrite: 
 
		Or DWORD PTR [0FF800000h + EBX * 4], 2 
		Jmp Done 
 
Fail: 
 
		Xor EAX, EAX 
 
Done: 
 
		Retf 
	} 
} 
 
// 使系统进入Ring0模式下 
GDTR gdtr; 
GDT_DESCRIPTOR *pGDTDescriptor; 
bool CallRing0(PVOID pvRing0FuncAddr, PVOID pvAddr, DWORD dwPageProtection) 
{ 
 
	bool Result; 
 
	if(pvAddr ==NULL) return false; 
 
	_asm Sgdt [gdtr] 
 
	pGDTDescriptor = (GDT_DESCRIPTOR *)(gdtr.dwGDTBase + 8); 
 
	// Search for a free GDT descriptor 
 
	for (WORD wGDTIndex = 1; wGDTIndex < (gdtr.wGDTLimit / 8); wGDTIndex++) 
	{ 
		if (pGDTDescriptor->Type == 0   && 
			pGDTDescriptor->System == 0 && 
			pGDTDescriptor->DPL == 0    && 
			pGDTDescriptor->Present == 0) 
		{ 
		// Found one ! 
		// Now we need to transform this descriptor into a callgate. 
		// Note that we're using selector 0x28 since it corresponds 
		// to a ring 0 segment which spans the entire linear address 
		// space of the processor (0-4GB). 
 
		CALLGATE_DESCRIPTOR *pCallgate; 
 
		pCallgate =	(CALLGATE_DESCRIPTOR *) pGDTDescriptor; 
		pCallgate->Offset_0_15 = LOWORD(pvRing0FuncAddr); 
		pCallgate->Selector = 0x28; 
		pCallgate->ParamCount =	0; 
		pCallgate->Unused = 0; 
		pCallgate->Type = 0xc;  // 386 call gate 
		pCallgate->System = 0;  // a system descriptor 
		pCallgate->DPL = 3;     // ring 3 code can call 
		pCallgate->Present = 1; 
		pCallgate->Offset_16_31 = HIWORD(pvRing0FuncAddr); 
 
		// Prepare the far call parameters 
 
		WORD CallgateAddr[3]; 
 
		CallgateAddr[0] = 0x0; 
		CallgateAddr[1] = 0x0; 
		CallgateAddr[2] = (wGDTIndex << 3) | 3; 
 
		// call Ring0ModifyPageProtection 
 
		_asm 
		{ 
			Mov ECX, [pvAddr] 
			Mov EDX, [dwPageProtection] 
			Cli 
			Call FWORD PTR [CallgateAddr] 
			Sti 
			Mov DWORD PTR [Result], EAX 
		} 
 
		// Now free the GDT descriptor 
 
		memset(pGDTDescriptor, 0, 8); 
 
		return Result; 
	} 
 
	// Advance to the next GDT descriptor 
	pGDTDescriptor++; 
	} 
 
	// Whoops, the GDT is full 
 
	return false; 
} 
 
// 改变内存状态为可读写 
BOOL RemovePageProtection(PVOID pvAddr) 
{ 
	return CallRing0((PVOID)Ring0ModifyPageProtection, pvAddr, PAGE_READWRITE); 
} 
 
 
BOOL SetPageProtection(PVOID pvAddr) 
{ 
	return CallRing0((PVOID)Ring0ModifyPageProtection, pvAddr, PAGE_READONLY); 
} 
 
#endif