学习自建调试体系(四)
这部分ring3和ring0通信,感觉也是实用的套路,先总结大致思路:
- hook NtTerminateProcess函数
- 有TerminateProcess请求到来时,判断参数二是否为固定常数(密钥),不是的话走原函数调用
- 如果参数二是约定好的密钥,参数一作为约定好的结构指针
- 读取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;
}