龙马谷

 找回密码
 立即注册

QQ登录

只需一步,快速开始

龙马谷VIP会员办理客服QQ:82926983(如果临时会话没有收到回复,请先加QQ好友再发。)
1 [已完结] GG修改器新手入门与实战教程 31课 2 [已完结] GG修改器美化修改教程 6课 3 [已完结] GG修改器Lua脚本新手入门教程 12课
4 [已完结] 触动精灵脚本新手入门必学教程 22课 5 [已完结] 手游自动化脚本入门实战教程 9课 6 [已完结] C++射击游戏方框骨骼透视与自瞄教程 27课
7 [已完结] C++零基础UE4逆向开发FPS透视自瞄教程 29课 8 [已完结] C++零基础大漠模拟器手游自动化辅助教程 22课 9 [已完结] C++零基础开发DXF内存脚本辅助教程 32课
以下是天马阁VIP教程,本站与天马阁合作,赞助VIP可以获得天马阁对应VIP会员,名额有限! 点击进入天马阁论坛
1 [已完结] x64CE与x64dbg入门基础教程 7课 2 [已完结] x64汇编语言基础教程 16课 3 [已完结] x64辅助入门基础教程 9课
4 [已完结] C++x64内存辅助实战技术教程 149课 5 [已完结] C++x64内存检测与过检测技术教程 10课 6 [已完结] C+x64二叉树分析遍历与LUA自动登陆教程 19课
7 [已完结] C++BT功能原理与x64实战教程 29课 8 [已完结] C+FPS框透视与自瞄x64实现原理及防护思路
查看: 4906|回复: 0

VT 基本框架源码

[复制链接]

15

主题

11

回帖

32

积分

编程入门

Rank: 1

龙马币
58

1.查询CPU对VMX的支持
cpuid 指令,查询1号功能,返回的ECX[5]==1
  1.   #define CPUID_ECX_VMX_ABILITY (1<<5)
  2.   ULONG64 CheckCPUID() {

  3.       int ctx[4] = { 0 };//顺序:eax,ebx,ecx,edx
  4.       __cpuid(ctx, 1);

  5.       return ctx[2] & CPUID_ECX_VMX_ABILITY;        //Bit-5
  6.   }
复制代码

rdmsr 指令,查询BIOS是否已开启对VMX的支持
  1.   #define MSR_IA32_FEATURE_CONTROL 0x3A
  2.   ULONG64 CheckMsr() {
  3.       MSR_IA32_FEATURE_CONTROL_REGISTER msr = { 0 };
  4.       msr.value.QuadPart = __readmsr(MSR_IA32_FEATURE_CONTROL);
  5.       return msr.Bits.Lock;
  6.   }
复制代码


2.开启VMX
修正CR0和CR4,设置CR4.VMXE=1
  1.   #define        MSR_IA32_VMX_CR0_FIXED0                                0x486
  2.   #define        MSR_IA32_VMX_CR0_FIXED1                                0x487
  3.   #define        MSR_IA32_VMX_CR4_FIXED0                                0x488
  4.   #define        MSR_IA32_VMX_CR4_FIXED1                                0x489
  5.   ULONG64 FixCr0() {

  6.       IA32_CR0 uCr0 = { 0 };
  7.       uCr0.value.QuadPart = __readcr0();

  8.       uCr0.value.QuadPart |= __readmsr(MSR_IA32_VMX_CR0_FIXED0);
  9.       uCr0.value.QuadPart &= __readmsr(MSR_IA32_VMX_CR0_FIXED1);

  10.       __writecr0(uCr0.value.QuadPart);
  11.       return TRUE;
  12.   }
  13.   ULONG64 FixCr4() {

  14.       IA32_CR4 uCr4 = { 0 };
  15.       uCr4.value.QuadPart = __readcr4();

  16.       uCr4.value.QuadPart |= __readmsr(MSR_IA32_VMX_CR4_FIXED0);
  17.       uCr4.value.QuadPart &= __readmsr(MSR_IA32_VMX_CR4_FIXED1);
  18.       uCr4.Bits.VMXE = 1;

  19.       __writecr4(uCr4.value.QuadPart);
  20.       return TRUE;
  21.   }
复制代码

3.申请内存
VMON区,需要页对齐,并且需要得到它的物理地址
VMCS区,需要页对齐,并且需要得到它的物理地址
VMM栈,可以的话申请几个页,避免栈溢出
  1.   ULONG64 CreateVM(UCHAR CpuIndex) {

  2.       psVM[CpuIndex].pOnVa = ExAllocatePool2(POOL_FLAG_NON_PAGED, PAGE_SIZE, 'VMON');
  3.       if (!psVM[CpuIndex].pOnVa) { return FALSE; }
  4.       RtlZeroMemory(psVM[CpuIndex].pOnVa, PAGE_SIZE);
  5.       psVM[CpuIndex].pOnPa = MmGetPhysicalAddress(psVM[CpuIndex].pOnVa);

  6.       psVM[CpuIndex].pCsVa = ExAllocatePool2(POOL_FLAG_NON_PAGED, PAGE_SIZE, 'VMCS');
  7.       if (!psVM[CpuIndex].pCsVa) { return FALSE; }
  8.       RtlZeroMemory(psVM[CpuIndex].pCsVa, PAGE_SIZE);
  9.       psVM[CpuIndex].pCsPa = MmGetPhysicalAddress(psVM[CpuIndex].pCsVa);

  10.       psVM[CpuIndex].pStack = ExAllocatePool2(POOL_FLAG_NON_PAGED, STACK_SIZE, 'VMSK');
  11.       if (!psVM[CpuIndex].pStack) { return FALSE; }
  12.       RtlZeroMemory(psVM[CpuIndex].pStack, STACK_SIZE);

  13.       return TRUE;
  14.   }
复制代码

4.设置VMXON区,执行VMXON
只需要填写一个版本号
执行vmxon(VMON区的物理地址);
  1.   ULONG64 InitVmxON(UCHAR CpuIndex, ULONG RevisonId) {

  2.       *((PULONG)psVM[CpuIndex].pOnVa) = RevisonId;

  3.       if (__vmx_on(&psVM[CpuIndex].pOnPa.QuadPart))
  4.       {
  5.           KdPrint(("vmx_on 失败!\n"));
  6.           return FALSE;
  7.       }

  8.       return TRUE;
  9.   }
复制代码

5.设置VMXCS区
5.1.初始化VMCS
  1.       ULONG64 InitVmxCS(UCHAR CpuIndex, ULONG RevisonId) {

  2.           *((PULONG)psVM[CpuIndex].pCsVa) = RevisonId;

  3.           if (__vmx_vmclear(&psVM[CpuIndex].pCsPa.QuadPart))
  4.               return FALSE;
  5.           if (__vmx_vmptrld(&psVM[CpuIndex].pCsPa.QuadPart))
  6.               return FALSE;

  7.           return TRUE;
  8.       }
复制代码

2.设置GUEST运行环境
控制寄存器:CR0,CR3,CR4
调试寄存器:DR7
段寄存器:ES,FS,DS,CS,SS,GS,TR,LDTR
GS基址,FS基址
GDT基址,IDT基址
GDT段限,IDT段限
状态寄存器:RFLAGS
SYSENTER_CS,SYSENTER_ESP,SYSENTER_EIP
RIP,RSP
需要保存GUEST当前的RSP和GUEST当前下一条指令的RIP,以便操作完成后回到GUEST的代码流程,就像没有发生过什么事一样
  1.   ULONG64 SetGuestState(ULONG64 GuestRip, ULONG64 GuestRsp) {

  2.       ULONG64 ret = 0;

  3.       ULONG64 GdtBase = _readBaseGDT();
  4.       ULONG64 IdtBase = _readBaseIDT();

  5.       ret += __vmx_vmwrite(GUEST_CR0, __readcr0());
  6.       ret += __vmx_vmwrite(GUEST_CR3, __readcr3());
  7.       ret += __vmx_vmwrite(GUEST_CR4, __readcr4());
  8.       ret += __vmx_vmwrite(GUEST_DR7, __readdr(7));

  9.       ret += SetGuestSeg(ES, _readES(), GdtBase);
  10.       ret += SetGuestSeg(FS, _readFS(), GdtBase);
  11.       ret += SetGuestSeg(DS, _readDS(), GdtBase);
  12.       ret += SetGuestSeg(CS, _readCS(), GdtBase);
  13.       ret += SetGuestSeg(SS, _readSS(), GdtBase);
  14.       ret += SetGuestSeg(GS, _readGS(), GdtBase);
  15.       ret += SetGuestSeg(TR, _readTR(), GdtBase);
  16.       ret += SetGuestSeg(LDTR, _readLDTR(), GdtBase);

  17.       ret += __vmx_vmwrite(GUEST_FS_BASE, __readmsr(MSR_IA32_FS_BASE));
  18.       ret += __vmx_vmwrite(GUEST_GS_BASE, __readmsr(MSR_IA32_GS_BASE));
  19.       ret += __vmx_vmwrite(GUEST_GDTR_BASE, GdtBase);
  20.       ret += __vmx_vmwrite(GUEST_GDTR_LIMIT, _readLimitGDT());
  21.       ret += __vmx_vmwrite(GUEST_IDTR_BASE, IdtBase);
  22.       ret += __vmx_vmwrite(GUEST_IDTR_LIMIT, _readLimitIDT());

  23.       ret += __vmx_vmwrite(GUEST_RFLAGS, __readeflags());
  24.       ret += __vmx_vmwrite(GUEST_RIP, GuestRip);
  25.       ret += __vmx_vmwrite(GUEST_RSP, GuestRsp);

  26.       ret += __vmx_vmwrite(GUEST_IA32_SYSENTER_CS, __readmsr(MSR_IA32_SYSENTER_CS));
  27.       ret += __vmx_vmwrite(GUEST_IA32_SYSENTER_ESP, __readmsr(MSR_IA32_SYSENTER_ESP));
  28.       ret += __vmx_vmwrite(GUEST_IA32_SYSENTER_EIP, __readmsr(MSR_IA32_SYSENTER_EIP));

  29.       return ret;
  30.   }
复制代码

3.设置HOST运行环境
控制寄存器:CR0,CR3,CR4
段寄存器:ES,FS,DS,CS,SS,GS,TR
GS基址,FS基址,TR基址
GDT基址,IDT基址
SYSENTER_CS,SYSENTER_ESP,SYSENTER_EIP
RIP,RSP
HOST的RIP就是VM退出后跳转到VMM的入口地址,所以我们要写一个VMM入口函数,保存VM的现场状态,回到VM后才能继续像什么也没发生过一样继续执行
  1.     ULONG64 SetHostState(ULONG64 HostRip, ULONG64 HostRsp) {

  2.         SEG seg = { 0 };
  3.         ULONG64 ret = 0;
  4.         ULONG64 GdtBase = _readBaseGDT();
  5.         ULONG64 IdtBase = _readBaseIDT();
  6.         ULONG64 TR = GetSegInfo(&seg, _readTR(), GdtBase);

  7.         ret += __vmx_vmwrite(HOST_CR0, __readcr0());
  8.         ret += __vmx_vmwrite(HOST_CR3, __readcr3());
  9.         ret += __vmx_vmwrite(HOST_CR4, __readcr4());

  10.         ret += __vmx_vmwrite(HOST_RIP, HostRip);
  11.         ret += __vmx_vmwrite(HOST_RSP, HostRsp);

  12.         ret += __vmx_vmwrite(HOST_CS_SELECTOR, _readCS() & 0xF8);
  13.         ret += __vmx_vmwrite(HOST_SS_SELECTOR, _readSS() & 0xF8);
  14.         ret += __vmx_vmwrite(HOST_DS_SELECTOR, _readDS() & 0xF8);
  15.         ret += __vmx_vmwrite(HOST_ES_SELECTOR, _readES() & 0xF8);
  16.         ret += __vmx_vmwrite(HOST_FS_SELECTOR, _readFS() & 0xF8);
  17.         ret += __vmx_vmwrite(HOST_GS_SELECTOR, _readGS() & 0xF8);
  18.         ret += __vmx_vmwrite(HOST_TR_SELECTOR, _readTR() & 0xF8);

  19.         ret += __vmx_vmwrite(HOST_FS_BASE, __readmsr(MSR_IA32_FS_BASE));
  20.         ret += __vmx_vmwrite(HOST_GS_BASE, __readmsr(MSR_IA32_GS_BASE));
  21.         ret += __vmx_vmwrite(HOST_TR_BASE, TR ? seg.Base : 0);
  22.         ret += __vmx_vmwrite(HOST_GDTR_BASE, GdtBase);
  23.         ret += __vmx_vmwrite(HOST_IDTR_BASE, IdtBase);

  24.         ret += __vmx_vmwrite(HOST_IA32_SYSENTER_CS, __readmsr(MSR_IA32_SYSENTER_CS));
  25.         ret += __vmx_vmwrite(HOST_IA32_SYSENTER_ESP, __readmsr(MSR_IA32_SYSENTER_ESP));
  26.         ret += __vmx_vmwrite(HOST_IA32_SYSENTER_EIP, __readmsr(MSR_IA32_SYSENTER_EIP));

  27.         return ret;
  28.     }
复制代码


4.设置执行控制
先设置最基本的的条件
  1.     ULONG64 SetVmxExecutionCTLS(UCHAR CpuIndex, ULONG64 vmxctrl) {

  2.         UCHAR ret = 0;
  3.         ULONG64 value = 0;

  4.         MSR_IA32_VMX_PINBASED_CTLS_REGISTER PinBased = { 0 }, SetPinBase = { 0 };
  5.         MSR_IA32_VMX_PROCBASED_CTLS_REGISTER Primary = { 0 }, SetPrimary = { 0 };
  6.         MSR_IA32_VMX_PROCBASED_CTLS2_REGISTER Secondry = { 0 }, SetSecondry = { 0 };
  7.         MSR_IA32_VMX_PROCBASED_CTLS3_REGISTER Tertiary = { 0 };

  8.         PinBased.value.QuadPart = vmxctrl ? __readmsr(MSR_IA32_VMX_TRUE_PINBASED_CTLS) : __readmsr(MSR_IA32_VMX_PINBASED_CTLS);
  9.         /*在这里设置《PinBased》*/

  10.         value = SetControls(SetPinBase.value.QuadPart, PinBased.value);
  11.         ret += __vmx_vmwrite(PIN_BASED_VM_EXECUTION_CONTROLS, value);

  12.         Primary.value.QuadPart = vmxctrl ? __readmsr(MSR_IA32_VMX_TRUE_PROCBASED_CTLS) : __readmsr(MSR_IA32_VMX_PROCBASED_CTLS);
  13.         /*在这里设置《Primary》*/
  14.         SetPrimary.Bits->MSRmap = TRUE;
  15.         SetPrimary.Bits->RDTSC = TRUE;
  16.         SetPrimary.Bits->Secondary = TRUE;

  17.         value = SetControls(SetPrimary.value.QuadPart, Primary.value);
  18.         ret += __vmx_vmwrite(PRIMARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, value);

  19.         if (SetPrimary.Bits->Secondary)
  20.         {
  21.             Secondry.value.QuadPart = __readmsr(MSR_IA32_VMX_PROCBASED_CTLS2);

  22.             /*在这里设置《Secondry》*/
  23.             SetSecondry.Bits->XSAVES_XRSTORS = TRUE;
  24.             SetSecondry.Bits->INVPCID = TRUE;
  25.             SetSecondry.Bits->RDTSCP = TRUE;

  26.             value = SetControls(SetSecondry.value.QuadPart, Secondry.value);
  27.             ret += __vmx_vmwrite(SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, value);

  28.         }
  29.         
  30.         ret += __vmx_vmwrite(VMCS_LINK_POINTER_FULL, ~0Ull);
  31.         ret += __vmx_vmwrite(VIRTUAL_PROCESSOR_IDENTIFIER, CpuIndex);

  32.         return ret;
  33.     }
复制代码


5.设置VM退出控制
先设置最基本的的条件
  1.     ULONG64 SetVmxExitCTLS(UCHAR CpuIndex, ULONG64 vmxctrl) {

  2.         ULONG64 ret = 0;            
  3.         ULONG64 value = 0;
  4.         MSR_IA32_VMX_EXIT_CTLS_REGISTER VmExit = { 0 }, SetExit = { 0 };
  5.         VmExit.value.QuadPart = vmxctrl ? __readmsr(MSR_IA32_VMX_TRUE_EXIT_CTLS) : __readmsr(MSR_IA32_VMX_EXIT_CTLS);
  6.         /*在这里设置《VmExit》*/
  7.         SetExit.Bits->HOST_addr_size = TRUE;

  8.         value = SetControls(SetExit.value.QuadPart, VmExit.value);
  9.         ret += __vmx_vmwrite(PRIMARY_VM_EXIT_CONTROLS, value);

  10.         return ret;
  11.     }
复制代码


6.设置VM进入控制
先设置最基本的的条件
  1.     ULONG64 SetVmxEntryCTLS(UCHAR CpuIndex, ULONG64 vmxctrl) {

  2.         ULONG64 ret = 0;
  3.         ULONG64 value = 0;
  4.         MSR_IA32_VMX_ENTRY_CTLS_REGISTER VmEntry = { 0 }, SetEntry = { 0 };
  5.         VmEntry.value.QuadPart = vmxctrl ? __readmsr(MSR_IA32_VMX_TRUE_ENTRY_CTLS) : __readmsr(MSR_IA32_VMX_ENTRY_CTLS);
  6.         /*在这里设置《VmEntry》*/
  7.         SetEntry.Bits->Guest_IA32e = TRUE;

  8.         value = SetControls(SetEntry.value.QuadPart, VmEntry.value);
  9.         ret += __vmx_vmwrite(VM_ENTRY_CONTROLS, value);

  10.         return ret;
  11.     }
复制代码


7.编写VMM处理函数
此函数只做一些准备工作。
  1.     ULONG64 HostEntry(PGUESTREG pGuestRegs)
  2.     {
  3.         __vmx_vmread(VIRTUAL_PROCESSOR_IDENTIFIER, &pGuestRegs->CpuIndex);
  4.         __vmx_vmread(EXIT_REASON,  (size_t*) & pGuestRegs->exitReason);

  5.         __vmx_vmread(GUEST_RIP, &pGuestRegs->GuestRip);
  6.         __vmx_vmread(GUEST_RSP, &pGuestRegs->GuestRsp);
  7.         __vmx_vmread(GUEST_RFLAGS, &pGuestRegs->GuestFlag);
  8.         __vmx_vmread(VM_EXIT_INSTRUCTION_LENGTH, &pGuestRegs->InstrLen);

  9.         pGuestRegs->eProcess = PsGetCurrentProcess();
  10.         pGuestRegs->eThread = PsGetCurrentThread();

  11.         return DispatchHandler(pGuestRegs);
  12.     }
复制代码


调用 DispatchHandler 来处理事件。以下只是处理一些必须要处理的指令,CPU不同可能会有差异。处理方法就是查看CPU手册,模仿指令行为。这里就省略了,以免读者看得不清晰
  1.     ULONG64 DispatchHandler(PGUESTREG pGuestRegs)
  2.     {
  3.         EXIT_REASON_FIELDS* exit = (EXIT_REASON_FIELDS*)&pGuestRegs->exitReason;
  4.         ULONG64 CpuIndex = pGuestRegs->CpuIndex;
  5.         ULONG64 GuestRip = pGuestRegs->GuestRip;
  6.         ULONG64 GuestRsp = pGuestRegs->GuestRsp;
  7.         ULONG64 InstrLen = pGuestRegs->InstrLen;

  8.         switch (exit->Bits.Basic)
  9.         {
  10.         case EXIT_REASON_CPUID: {
  11.            ...
  12.             break;
  13.         }
  14.         case EXIT_REASON_RDMSR: {
  15.            ...
  16.             break;
  17.         }
  18.         case EXIT_REASON_WRMSR: {
  19.            ...
  20.             break;
  21.         }
  22.         case EXIT_REASON_RDTSC: {
  23.             ...
  24.             break;
  25.         }
  26.         case EXIT_REASON_RDTSCP: {
  27.            ...
  28.             break;
  29.         }                           
  30.         default:
  31.             DbgBreakPoint();
  32.             break;
  33.         }
  34.         return TRUE;
  35.     }
复制代码


6.执行VM
执行vmlaunch();
如果上述设置没有出现问题。代码会接着在我们设置好的GUEST.RIP处继续运行。
直到触发VM退出条件,即可进入我们设置好的VMM.RIP(HostEntry)处开始执行

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

龙马谷| C/C++辅助教程| 安卓逆向安全| 论坛导航| 免责申明|Archiver|
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表龙马谷立场!
任何人不得以任何方式翻录、盗版或出售本站视频,一经发现我们将追究其相关责任!
我们一直在努力成为最好的编程论坛!
Copyright© 2018-2021 All Right Reserved.
在线客服
快速回复 返回顶部 返回列表