Understanding virtdbg

Forum for announcements and questions about tools and software.
Post Reply
pwl
Posts: 6
Joined: Sat Jul 01, 2017 7:44 pm

Understanding virtdbg

Post by pwl » Sat Jul 01, 2017 8:07 pm

I'm reading https://github.com/erynian/virtdbg sources and have trouble understanding this code:

Code: Select all

    for (i = 0; i < KeNumberProcessors; i++) 
    {
        OldAffinity = KeSetSystemAffinityThreadEx((KAFFINITY) (1 << i));
        OldIrql = KeRaiseIrqlToDpcLevel();
        _StartVirtualization();
        KeLowerIrql(OldIrql);
        KeRevertToUserAffinityThreadEx(OldAffinity);
    }

Code: Select all

_StartVirtualization PROC
    ;int 3
	push	rax
	push	rcx
	push	rdx
	push	rbx
	push	rbp
	push	rsi
	push	rdi
	push	r8
	push	r9
	push	r10
	push	r11
	push	r12
	push	r13
	push	r14
	push	r15

	sub	rsp, 28h

	mov	rcx, rsp
	call	StartVirtualization
_StartVirtualization ENDP
Inside StartVirtualization, there is some VMX setup code and then a call to Virtualize:

Code: Select all

NTSTATUS Virtualize(PVIRT_CPU pCpu)
{
/*    ULONG64 rsp;*/
    ULONG32 i;
    
    i = KeGetCurrentProcessorNumber();
    DbgLog(("CPU: 0x%p \n", pCpu));
    DbgLog(("rsp: 0x%llx \n", _Rsp()));

    _VmLaunch();
    /* never returns if successful */
So we have a call tree that ends in vmlaunch that starts exexuting guest code if successful and doesn't return! How is the topmost loop going to terminate then, or proceed to virtualize more than 1 processors?

dmr
Posts: 1
Joined: Mon Nov 17, 2014 11:09 pm

Re: Understanding virtdbg

Post by dmr » Mon Jul 03, 2017 6:43 am

You need to read Intel manuals, iirc, especially 3C. The answer you're looking for is there.

User avatar
feryno
Posts: 42
Joined: Mon Jan 09, 2012 2:46 pm
Location: Czechoslovakia
Contact:

Re: Understanding virtdbg

Post by feryno » Thu Jul 06, 2017 10:48 am

@dmr:
pwl will read hundreds pages of manual for very long time until finding the answer

@pwl:
on successful vmlaunch, the RIP (x64) / EIP (x86) is obtained from VMCS (from guest RIP), also RSP (x64) / ESP (x86) (from guest RSP), also a lot of other things like selectors (CS, SS, DS, ES, FS, GS) and their bases/limits/access rights, control registers (CR0, CR3, CR4), LDTR, TR, GDT, IDT, ...

to make things clear and understandable, the best would be to point the guest RIP to the address immediately following the vmlaunch instruction

but because C / NASM does not allow you to access a label inside a proc from different proc, the author of virtdbg used some tricks to make things running:
he set guest RIP to the _GuestEntryPoint
he set guest RSP to the RSP at the time of call StartVirtualization (the only one param passed in RCX to the proc StartVirtualization is the actual RSP)

this way the epilogues either RET instructions of triple procedures StartVirtualization / _Virtualize / _VmLaunch are not reached in case of vmlaunch success (but would be executed in case of vmlaunch failure)
this is quite dangerous, imagine that the prologue of any of the _Virtualize / StartVirtualization proc pushed some nonvolatile registers and proc overwrote with own values (RBX, RBP, RSI, RDI, R11-R15) - usage of such registers completely depends on decision of C compiler - to survive this the guest RIP points to a proc GuestEntryPoint which pops all registers in reverse order as they were pushed on _StartVirtualization
hypervisor-based solutions developer (Intel, AMD)

pwl
Posts: 6
Joined: Sat Jul 01, 2017 7:44 pm

Re: Understanding virtdbg

Post by pwl » Fri Jul 07, 2017 6:30 pm

Indeed, intel manuals are huge, I just started to learn about VT-x.
Thanks for the answer feryno.

Post Reply