Loading

学习自建调试体系(四)

这部分ring3和ring0通信,感觉也是实用的套路,先总结大致思路:

  1. hook NtTerminateProcess函数
  2. 有TerminateProcess请求到来时,判断参数二是否为固定常数(密钥),不是的话走原函数调用
  3. 如果参数二是约定好的密钥,参数一作为约定好的结构指针
  4. 读取ring3传来的数据,读取数据,执行约定函数

SSDT hook

NTSTATUS DbgObjHookNtTerminateProcess()
{
	PULONG  Address;
	PVOID Temp;

	if ((ULONG)OldNtTerminateProcess)		//static变量初始化0 
	{
		return STATUS_UNSUCCESSFUL;
	}

	//
	// 在SSDT表中获取到NtTerminateProcess的地址
	//

	Address = (PULONG)((ULONG)KeServiceDescriptorTable->ntoskrnl.ServiceTable +
		257 * 4);

	//原函数 and 替换函数
	OldNtTerminateProcess = (PZWTERMINATEPROCESS)* Address;
	Temp = &NewNtTerminateProcess;

	//
	// 改写SSDT表中NtTerminateProcess的地址
	//

	//自己封装的MoveMemory函数
	SafeCopyMemory(Address, &Temp, sizeof(PVOID));

	KdPrint(("Ddvp-> 旧NtTerminateProcess地址: %p, 新的NtTerminateProcess地址: %p \n",
		OldNtTerminateProcess, &NewNtTerminateProcess));

	return STATUS_SUCCESS;

}

钩子函数

NTSTATUS
NewNtTerminateProcess(
HANDLE   hProcess,
NTSTATUS ExitStatus
)
{
	NTSTATUS Status;
	BUFFER_LOCK InBufferLock;
	BUFFER_LOCK OutBufferLock;
	SYSTEM_CALL  SysCall;

	//typedef struct tagSystemCall
	//{
	//	int Number;
	//	PVOID lpInBuffer;
	//	ULONG ulInBufferSize;
	//	PVOID lpOutBuffer;
	//	ULONG ulOutBufferSize;
	//}SYSTEM_CALL, *PSYSTEM_CALL;

	PEPROCESS Process = PsGetCurrentProcess();

	//
	// 如果调用过来的是用户态, 并且Key也相同
	//
	if ((ExGetPreviousMode() == UserMode) && (ExitStatus == 0x750C530D))
	{
		Status = STATUS_UNSUCCESSFUL;
		InBufferLock.lpData = NULL;
		OutBufferLock.lpData = NULL;

		do
		{
			__try
			{
				//
				// 检查用户模式缓冲区是否正确对齐.注意是用户模式缓冲区
				//
              
              /////hProcess作为pSysCall解释
				ProbeForRead(hProcess, sizeof(SYSTEM_CALL), 1);

				//
				// 复制 一个 syscall结构过来
				//
				fastcpy(&SysCall, hProcess, sizeof(SYSTEM_CALL));
			}
			__except (EXCEPTION_EXECUTE_HANDLER)
			{
				Status = GetExceptionCode();
				break;
			}

			//
			// 参数判断
			//
			if ((SysCall.Number > SC_MAX) ||
				(SysCall.ulInBufferSize  > SC_DAT_LIMIT) ||
				(SysCall.ulOutBufferSize > SC_DAT_LIMIT))
			{
				KdPrint(("Ddvp-> NewNtTerminateProcess Buffer 有问题 \n"));
				break;
			}

			//
			// 如果输入缓冲区不为NULL, 那么锁定输入缓冲区
			//
			if (SysCall.lpInBuffer != NULL)
			{
				if (DbgLockBuffer(&InBufferLock, SysCall.lpInBuffer, SysCall.ulInBufferSize) == 0)
				{
					KdPrint(("Ddvp-> NewNtTerminateProcess In Buffer Lock Error! \n"));
					break;
				}

				SysCall.lpInBuffer = InBufferLock.lpData;
			}

			//
			// 如果输出缓冲区不为NULL, 那么锁定输入缓冲区
			//
			if (SysCall.lpOutBuffer != NULL)
			{
				if (DbgLockBuffer(&OutBufferLock, SysCall.lpOutBuffer, SysCall.ulOutBufferSize) == 0)
				{
					KdPrint(("Ddvp-> NewNtTerminateProcess Out Buffer Lock Error! \n"));
					break;
				}

				SysCall.lpOutBuffer = OutBufferLock.lpData;
			}

			//
			// 执行约定的函数,哪个函数,什么通信数据都在SysCall结构中
			//
			if (NT_SUCCESS(SysCallTable[SysCall.Number](&SysCall)))
			{
				Status = STATUS_SUCCESS;
			}
		} while (0);

		if (InBufferLock.lpData != NULL)
		{
			DbgUnLockBuffer(&InBufferLock);
		}

		if (OutBufferLock.lpData != NULL)
		{
			DbgUnLockBuffer(&OutBufferLock);
		}
	}
	//---------------------------------------------------------------------------
	else
	{
			Status = OldNtTerminateProcess(hProcess, ExitStatus);
	}

	return Status;
}

posted @ 2016-04-20 20:39  Lnju  阅读(665)  评论(0编辑  收藏  举报