- 注册时间
- 2011-3-6
- 最后登录
- 1970-1-1
该用户从未签到
|
感谢作者,以下这个知识点太实用了。不要以为在驱动层就可以直接调用NT*系列驱动函数了,有很多驱动函数必须修改模式才能调用。
记得之前再调用NT函数读写内存的时候就遇到问题,老是读取不了。其实代码没有错,而是没修改模式。
现在思路终于通了。直接给出源码范例,让更多新手少走外路。
-------------------------------------------------
需要先把Kthread中的PreviousMode的值置成KernelMode
因为调用CqEnumProcessInfoByMyOpenProcess这个函数的时候,是由应用层的程序调用DeviceIoControl进入内核的,所以要经过
Kifastcallentry,Kifastcallentry在执行中会把当前要进入内核的这个线程的PreviousMode设置成UserMode,所以当我调用NtOpenProcess时,NtOpenprocess在执行中会判断当前的调用模式,如果不改Kthread中的PreviousMode,NtOpenprocess发现是UserMode,所以要判断clientId则个参数的地址是不是用户层地址,当它发现这个地址是内核地址的时候,执行就是败了,所以要把当前线程的Ktrhead的PerviousMode这个值置成KernelMode,欺骗NtOpenProcess,,这样NtOpenProcess判断的时候就认为这个调用是内核的调用,所以就可以执行成功。
NTSTATUS CqEnumProcessInfoByMyOpenProcess(PPROCESS_INFO pProcessInfo)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
CLIENT_ID ClientId = {0};
ULONG i = 0;
HANDLE ProcessHandle = 0;
PEPROCESS Process = NULL;
PKTHREAD Kthread = NULL;
OBJECT_ATTRIBUTES ProcAttr = {0};
InitializeObjectAttributes(&ProcAttr, 0, 0, 0, 0);
Kthread = (PKTHREAD)PsGetCurrentThread();
*((PUCHAR)Kthread + CqGetOffset(enumPreviousModeOffsetByKthread)) = KernelMode;
for(i = 0; i < 65535; i++)
{
ClientId.UniqueProcess = (HANDLE)i;
Status = MyNtOpenProcess(&ProcessHandle, PROCESS_ALL_ACCESS , &ProcAttr, &ClientId);
if( STATUS_SUCCESS == Status )
{
Status = PsLookupProcessByProcessId(i, &Process);
if( STATUS_SUCCESS != Status )
{
goto Exit0;
}
Status = CqSetProcessInfoByEProcess(pProcessInfo, Process);
if( NULL != Process )
{
ObDereferenceObject(Process);
}
if( NULL != ProcessHandle )
{
ZwClose(ProcessHandle);
}
ProcessHandle = 0;
Process = 0;
i+=3;
}
else
{
continue;
}
}
*((PUCHAR)Kthread + CqGetOffset(enumPreviousModeOffsetByKthread)) = UserMode;
Status = STATUS_SUCCESS;
Exit0:
return Status;
} |
|