驱动编程:NtReadVirtualMemory

NtReadVirtualMemory函数位于ntdll中,作用就是把用户态的函数调用翻译成相应的系统调用,进入内核态。内核中一般有一个相同名字的处理函数,接收到该类型的系统调用后做实际的工作。

NTSTATUS STDCALL NtReadVirtualMemory(IN HANDLE ProcessHandle, IN PVOID BaseAddress, OUT PVOID Buffer, IN ULONG NumberOfBytesToRead, OUT PULONG NumberOfBytesRead) { NTSTATUS Status; PMDL Mdl; PVOID SystemAddress; PEPROCESS Process; DPRINT("NtReadVirtualMemory(ProcessHandle %x, BaseAddress %x, " "Buffer %x, NumberOfBytesToRead %d) ",ProcessHandle,BaseAddress, Buffer,NumberOfBytesToRead); Status = ObReferenceObjectByHandle(ProcessHandle, PROCESS_VM_WRITE, NULL, UserMode, (PVOID*)(&Process), NULL);
 
   if (Status != STATUS_SUCCESS)
   {
      return(Status);
   }

}
struct _EPROCESS
{
  /* Microkernel specific process state. */
  KPROCESS Pcb;
}
typedef struct _KPROCESS 
{
  DISPATCHER_HEADER 	DispatcherHeader;             /* 000 */
  LIST_ENTRY            ProfileListHead;              /* 010 */
  PHYSICAL_ADDRESS      DirectoryTableBase;           /* 018 这是cr3*/
}
   Mdl = MmCreateMdl(NULL,Buffer, NumberOfBytesToRead);
    MmProbeAndLockPages(Mdl,UserMode,IoWriteAccess);
  KeAttachProcess(Process);
  SystemAddress = MmGetSystemAddressForMdl(Mdl);
   memcpy(SystemAddress, BaseAddress, NumberOfBytesToRead);
  KeDetachProcess();
  if (Mdl->MappedSystemVa != NULL)
   {
      MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
   }
   MmUnlockPages(Mdl);
   ExFreePool(Mdl);

   ObDereferenceObject(Process);

   *NumberOfBytesRead = NumberOfBytesToRead;
   return(STATUS_SUCCESS);
}
 memcpy(Buffer, BaseAddress, NumberOfBytesToRead);
VOID STDCALL
KeAttachProcess (PEPROCESS Process)
{
   KIRQL oldlvl;
   PETHREAD CurrentThread;
   PULONG AttachedProcessPageDir;
   ULONG PageDir;
   
   DPRINT("KeAttachProcess(Process %x)
",Process);
   
   CurrentThread = PsGetCurrentThread();

   if (CurrentThread->OldProcess != NULL)
     {
	DbgPrint("Invalid attach (thread is already attached)
");
	KEBUGCHECK(0);
     }
   
   KeRaiseIrql(DISPATCH_LEVEL, &oldlvl);

   KiSwapApcEnvironment(&CurrentThread->Tcb, &Process->Pcb);
 /* The stack of the current process may be located in a page which is
      not present in the page directory of the process we're attaching to.
      That would lead to a page fault when this function returns. However,
      since the processor can't call the page fault handler 'cause it can't
      push EIP on the stack, this will show up as a stack fault which will
      crash the entire system.
      To prevent this, make sure the page directory of the process we're
      attaching to is up-to-date. */

   AttachedProcessPageDir = ExAllocatePageWithPhysPage(Process->Pcb.DirectoryTableBase);
   MmUpdateStackPageDir(AttachedProcessPageDir, &CurrentThread->Tcb);
   ExUnmapPage(AttachedProcessPageDir);
 CurrentThread->OldProcess = PsGetCurrentProcess();
   CurrentThread->ThreadsProcess = Process;
   PageDir = Process->Pcb.DirectoryTableBase.u.LowPart;
   DPRINT("Switching process context to %x
",PageDir);
   Ke386SetPageTableDirectory(PageDir);
   KeLowerIrql(oldlvl);
}
原文地址:https://www.cnblogs.com/alsofly/p/3734814.html