内核中读取指定进程的内存空间
2021-07-01
402
0
Windows驱动运行于内核中,应用层的所有进程共享。
在应用层中,windows提供了如通过系统调用进入到内核中。
在应用层不能直接引用或使用内核的地址。但在内核中,是可以使用应用层的地址的。
但是由于进程的调度,当我们在内核中操作应用层的地址时,可能随时发生进程切换,这时我们使用的内存地址可能因为进程的切换而读取到别的进程中。
在Windows内核中,为了使操作应用层地址,可以将内核的当前环境附加到进程中,这样就可以保证后续的操作就一直针对指定进程中的。
下面我们通过一个函数读取指定进程内存空间示例来说明具体的流程:
- 根据进程ID使用PsLookupProcessByProcessId获取进程的指针PEPROCESS。
- 分配非分页内存空间KAPC_STATE。
- 使用KeStackAttachProcess将当前线程附加到指定的进程。
- 读取内存….
- 将当前线程从指定进程剥离KeUnstackDetachProcess
- 资源回收非分页内存空间KAPC_STATE
代码如下:
const NTSTATUS ReadProcessMemory(const int procId, const void* pAddress, void* const pOutBuffer, const DWORD readSize)
{
PEPROCESS。
pProcess;
NTSTATUS retVal;
PKAPC_STATE apcState = NULL;
// Look up the process object using the process ID.
retVal = PsLookupProcessByProcessId((HANDLE)procId, &pProcess);
if (retVal != STATUS_SUCCESS)
{
return retVal;
}
__try
{
// Allocate APC state block.
apcState = ExAllocatePool(NonPagedPool, sizeof(KAPC_STATE));
__try
{
// Attach the current thread to the address space of the process.
KeStackAttachProcess(pProcess, apcState);
// Copy the memory block to the specified buffer.
RtlCopyMemory(pOutBuffer, pAddress, readSize);
retVal = STATUS_SUCCESS;
}
__finally
{
// Detach the process and free the APC state block.
KeUnstackDetachProcess(apcState);
ExFreePool(apcState);
}
}
__except (1)
{
retVal = STATUS_UNSUCCESSFUL;
}
// Dereference the process object pointer.
ObDereferenceObject(pProcess);
return retVal;
}