Rootkits——windows内核的安全防护(4)

在计算机组成当中,每一个硬件模块都有专属于自己的寄存器,这些寄存器用于短时间内保存自己的数据,接受命令用于下一步执行,或者保存硬件的状态。而这些寄存器可以通过相应的端口进行访问这些寄存器。

NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
{
	LARGE_INTEGER timeout;

	theDriverObject->DriverUnload  = OnUnload; 

	gTimer = (PKTIMER)ExAllocatePool(NonPagedPool,sizeof(KTIMER));
	gDPCP = (PKDPC)ExAllocatePool(NonPagedPool,sizeof(KDPC));

	timeout.QuadPart = -10;

	KeInitializeTimer( gTimer );
	KeInitializeDpc( gDPCP, timerDPC, NULL );

	if(TRUE == KeSetTimerEx( gTimer, timeout, 300, gDPCP))	// 300 ms timer	
	{
		DbgPrint("Timer was already queued..");
	}

	return STATUS_SUCCESS;
}

首先在驱动入口程序设置一个定时器以及相应的定时器处理函数,定时器每隔300ms进行一次异步的定时处理程序进行一次处理。而与DPC相关联的异步处理函数式timerDPC,下一步进入到timerDPC的分析。

VOID timerDPC(	IN PKDPC Dpc,
	IN PVOID DeferredContext,
	IN PVOID sys1,
	IN PVOID sys2)
{
	SetLEDS( g_key_bits++ );
	if(g_key_bits > 0x07) g_key_bits = 0;
}

timerDPC当中对键盘LED进行设置,然后在键盘按键计数大于7的时候,对键盘计数进行清0

void SetLEDS( UCHAR theLEDS )
{
	if(FALSE == SendKeyboardCommand( 0xED ))
	{
		DbgPrint("SetLEDS::error sending keyboard command\n");
	}

	// send the flags for the LEDS
	if(FALSE == SendKeyboardCommand( theLEDS ))
	{
		DbgPrint("SetLEDS::error sending keyboard command\n");
	}
}
ULONG SendKeyboardCommand( IN UCHAR theCommand )
{
	char _t[255];

	if(TRUE == WaitForKeyboard())
	{
		DrainOutputBuffer();

		_snprintf(_t, 253, "SendKeyboardCommand::sending byte %02X to port 0x60\n", theCommand);
		DbgPrint(_t);

		WRITE_PORT_UCHAR( KEYBOARD_PORT_60, theCommand );

		DbgPrint("SendKeyboardCommand::sent\n");
	}
	else
	{
		DbgPrint("SendKeyboardCommand::timeout waiting for keyboard\n");
		return FALSE;
	}

	// TODO: wait for ACK or RESEND from keyboard	

	return TRUE;
}

函数首先等待输入缓冲标志为满,然后对缓冲进行排空,然后利用0X60端口写入命令。

ULONG WaitForKeyboard()
{
	char _t[255];
	int i = 100;	// number of times to loop
	UCHAR mychar;

	DbgPrint("waiting for keyboard to become accecssable\n");
	do
	{
		mychar = READ_PORT_UCHAR( KEYBOARD_PORT_64 );

		KeStallExecutionProcessor(666);

		_snprintf(_t, 253, "WaitForKeyboard::read byte %02X from port 0x64\n", mychar);
		DbgPrint(_t);

		if(!(mychar & IBUFFER_FULL)) break;	// if the flag is clear, we go ahead
	}
	while (i--);

	if(i) return TRUE;
	return FALSE;
}

在等待函数当中,首先读取端口数据,然后建等待,再看看其中的INPUTBUFFER标志是否被标上。

void DrainOutputBuffer()
{
	char _t[255];
	int i = 100;
	UCHAR c;

	DbgPrint("draining keyboard buffer\n");
	do
	{
		c = READ_PORT_UCHAR(KEYBOARD_PORT_64);

		KeStallExecutionProcessor(666);

		_snprintf(_t, 253, "DrainOutputBuffer::read byte %02X from port 0x64\n", c);
		DbgPrint(_t);

		if(!(c & OBUFFER_FULL)) break;	// if the flag is clear, we go ahead

		// gobble up the byte in the output buffer
		c = READ_PORT_UCHAR(KEYBOARD_PORT_60);

		_snprintf(_t, 253, "DrainOutputBuffer::read byte %02X from port 0x60\n", c);
		DbgPrint(_t);
	}
	while (i--);
}

你可能感兴趣的:(C++,内核)