├── README.md ├── amd64 └── context.asm ├── context.h ├── frookSINATRA_virtualbox.diff ├── main.c └── sources /README.md: -------------------------------------------------------------------------------- 1 |
2 | FrookSINATRA 3 | is a kernel driver and a Virtualbox(Hypervisor) patch to make possible hook of the LSTAR, even with patchguard (Up-to-date Windows 8.1 on July 2014) activated. 4 | 5 | 6 | DRIVER: 7 | On Load, the driver: 8 | 1. saves the original lSTAR, 9 | 2. asks the hypervisor (MSR Knocking) to save the original LSTAR too, 10 | 3. writes the LSTAR to with the address of the hook function, 11 | 4. ... Working here ... 12 | 13 | On unload, the driver: 14 | 6. restores the old LSTAR 15 | 5. asks the hypervisor to forget the original LSTAR 16 | 17 | 18 | HYPERVISOR: 19 | I changed the virtualbox (Dirty patch again, sorry) VT-X hypervisor HMVMXR0.cpp, to intercept read and write of MSR. 20 | When the kernel writes a magic value on a magic MSR, the LSTAR is stored. 21 | Each time patchguard is executed, it asks the MSR like this asm("rdmsr 0xC000005") Patchguard MSR Request, the hypervisor intercepts the read, and give the original LSTAR value (legit one), even if it was hooked by the driver ! 22 | 23 | This is working because when a sysenter/syscall is made, the LSTAR MSR isn't read via rdmsr instruction, but read by the CPU itself, and hypervisor isn't called. So the instruction flow is redirected to the real value of the LSTAR, the hook function, if LSTAR is hooked. 24 | 25 | NOTE: 26 | The driver can be loaded with dsefix DSEFix 27 | The driver can work on Windows 7 x64 without the hypervisor 28 | 29 | TODO: 30 | * Make a version where all the thing is done in hypervisor, write the hook EIP in a magic MSR... 31 | * Make it working with AMD, 2 lines to change, 32 | * Could be integrated in (this nice tool) MiniHyperVisorProject, to make it working on a live Windows (bluePill+Intercept R/W MSR+frookSINATRA = Rootkit ;p) 33 | * Real syscall analysis...but this is a Poc... 34 |35 | -------------------------------------------------------------------------------- /amd64/context.asm: -------------------------------------------------------------------------------- 1 | EXTERN origKiSystemCall64:QWORD 2 | EXTERN myPrologKiSystemCall64:QWORD 3 | EXTERN syscall_number:QWORD 4 | 5 | .data 6 | 7 | .code 8 | 9 | ;Secure the registers and the stack :D 10 | myKiSystemCall64ASM PROC 11 | swapgs ;USER->KERNEL 12 | mov qword ptr gs:[10h],rsp ;save stack pointer 13 | mov rsp,qword ptr gs:[1a8h] ;get stack pointer 14 | sub rsp,4096h ;far far away ! 15 | 16 | ;TODO: FPU registers 17 | mov [rsp+8],rax ;save register 18 | mov [rsp+16],rbx 19 | mov [rsp+24],rcx 20 | mov [rsp+32],rdx 21 | mov [rsp+40],rsi 22 | mov [rsp+48],rdi 23 | mov [rsp+56],r8 24 | mov [rsp+64],r9 25 | mov [rsp+72],r10 26 | mov [rsp+80],r11 27 | mov [rsp+88],r12 28 | mov [rsp+96],r13 29 | mov [rsp+104],r14 30 | mov [rsp+112],r15 31 | sub rsp, 120 32 | 33 | mov qword ptr [syscall_number],rax 34 | 35 | call qword ptr [myPrologKiSystemCall64]; 36 | 37 | add rsp, 120 38 | mov rax,[rsp+8] ;restore register 39 | mov rbx,[rsp+16] 40 | mov rcx,[rsp+24] 41 | mov rdx,[rsp+32] 42 | mov rsi,[rsp+40] 43 | mov rdi,[rsp+48] 44 | mov r8,[rsp+56] 45 | mov r9,[rsp+64] 46 | mov r10,[rsp+72] 47 | mov r11,[rsp+80] 48 | mov r12,[rsp+88] 49 | mov r13,[rsp+96] 50 | mov r14,[rsp+104] 51 | mov r15,[rsp+112] 52 | 53 | mov rsp,qword ptr gs:[10h] ;restore original stack 54 | swapgs ;KERNEL->USER 55 | 56 | jmp [origKiSystemCall64] ;jmp to orginal KiSystemCall64 57 | myKiSystemCall64ASM ENDP 58 | 59 | END 60 | -------------------------------------------------------------------------------- /context.h: -------------------------------------------------------------------------------- 1 | void myKiSystemCall64ASM(void); 2 | -------------------------------------------------------------------------------- /frookSINATRA_virtualbox.diff: -------------------------------------------------------------------------------- 1 | diff -bur VirtualBox-4.3.12-orig/include/VBox/vmm/cpum.h VirtualBox-4.3.12/include/VBox/vmm/cpum.h 2 | --- VirtualBox-4.3.12-orig/include/VBox/vmm/cpum.h 2014-05-16 14:18:35.000000000 +0200 3 | +++ VirtualBox-4.3.12/include/VBox/vmm/cpum.h 2014-07-20 07:45:03.210379986 +0200 4 | @@ -420,6 +420,10 @@ 5 | VMM_INT_DECL(void) CPUMGuestLazyLoadHiddenSelectorReg(PVMCPU pVCpu, PCPUMSELREG pSReg); 6 | VMMR0_INT_DECL(void) CPUMR0SetGuestTscAux(PVMCPU pVCpu, uint64_t uValue); 7 | VMMR0_INT_DECL(uint64_t) CPUMR0GetGuestTscAux(PVMCPU pVCpu); 8 | + 9 | +//PG Bypass: Allow HMVMXR0.cpp to read the LSTAR 10 | +VMMR0_INT_DECL(uint64_t) CPUMR0GetGuestMsrLSTAR(PVMCPU pVCpu); 11 | + 12 | /** @} */ 13 | diff -bur VirtualBox-4.3.12-orig/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp VirtualBox-4.3.12/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp 14 | --- VirtualBox-4.3.12-orig/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp 2014-05-16 14:27:25.000000000 +0200 15 | +++ VirtualBox-4.3.12/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp 2014-07-20 08:09:02.570235345 +0200 16 | @@ -1384,10 +1384,16 @@ 17 | } 18 | 19 | 20 | +static uint64_t myMsrLSTAR = 0; //used to update the LSTAR MSR 21 | +static uint64_t savedMsrLSTAR = 0; //used to store the clean LSTAR MSR 22 | /** @callback_method_impl{FNCPUMRDMSR} */ 23 | static DECLCALLBACK(int) cpumMsrRd_Amd64LongSyscallTarget(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue) 24 | { 25 | + if(savedMsrLSTAR){ // If savedMsrLSTAR is set, so give it :D 26 | + *puValue = savedMsrLSTAR; 27 | + }else{ 28 | *puValue = pVCpu->cpum.s.Guest.msrLSTAR; 29 | + } 30 | return VINF_SUCCESS; 31 | } 32 | 33 | @@ -1401,6 +1407,7 @@ 34 | return VERR_CPUM_RAISE_GP_0; 35 | } 36 | pVCpu->cpum.s.Guest.msrLSTAR = uValue; 37 | + myMsrLSTAR = uValue; 38 | return VINF_SUCCESS; 39 | } 40 | 41 | @@ -4950,6 +4957,7 @@ 42 | int rc; 43 | PVM pVM = pVCpu->CTX_SUFF(pVM); 44 | PCPUMMSRRANGE pRange = cpumLookupMsrRange(pVM, idMsr); 45 | + LogRel(("CPUM: RDMSR %#x (%s) -> %#llx\n", idMsr, pRange->szName, *puValue)); 46 | if (pRange) 47 | { 48 | CPUMMSRRDFN enmRdFn = (CPUMMSRRDFN)pRange->enmRdFn; 49 | @@ -4962,6 +4970,7 @@ 50 | STAM_REL_COUNTER_INC(&pVM->cpum.s.cMsrReads); 51 | 52 | rc = pfnRdMsr(pVCpu, idMsr, pRange, puValue); 53 | + LogRel(("CPUM: RDMSR %#x (%s) -> %#llx\n", idMsr, pRange->szName, *puValue)); 54 | if (RT_SUCCESS(rc)) 55 | { 56 | Log2(("CPUM: RDMSR %#x (%s) -> %#llx\n", idMsr, pRange->szName, *puValue)); 57 | @@ -4978,7 +4987,7 @@ 58 | } 59 | else 60 | { 61 | - Log(("CPUM: Unknown RDMSR %#x -> #GP(0)\n", idMsr)); 62 | + LogRel(("CPUM: Unknown RDMSR %#x -> #GP(0)\n", idMsr)); 63 | STAM_REL_COUNTER_INC(&pVM->cpum.s.cMsrReads); 64 | STAM_REL_COUNTER_INC(&pVM->cpum.s.cMsrReadsUnknown); 65 | rc = VERR_CPUM_RAISE_GP_0; 66 | @@ -5014,6 +5023,23 @@ 67 | int rc; 68 | PVM pVM = pVCpu->CTX_SUFF(pVM); 69 | PCPUMMSRRANGE pRange = cpumLookupMsrRange(pVM, idMsr); 70 | + 71 | +//Secret command to store the clean value of the LSTAR 72 | +#define SECRET_MSR 0x01234567 73 | +#define BYPASS_ACTIVATION 0xDEADDEADDEADDEAD 74 | +#define BYPASS_DESACTIVATION 0xC0DEC0DEC0DEC0DE 75 | + LogRel(("CPUM: WRMSR %#x (%s), %#llx [%#llx]\n", idMsr, pRange->szName, 0, uValue)); 76 | + if(idMsr == SECRET_MSR){ 77 | + if(uValue == BYPASS_ACTIVATION){ 78 | + savedMsrLSTAR = pVCpu->cpum.s.Guest.msrLSTAR; 79 | + LogRel(("[BYPASS_ACTIVATION] %p\n", savedMsrLSTAR)); 80 | + } 81 | + if(uValue == BYPASS_DESACTIVATION){ 82 | + savedMsrLSTAR = 0; 83 | + LogRel(("[BYPASS_DESACTIVATION] %p\n", savedMsrLSTAR)); 84 | + } 85 | + } 86 | + 87 | if (pRange) 88 | { 89 | STAM_COUNTER_INC(&pRange->cWrites); 90 | @@ -5589,4 +5615,15 @@ 91 | pVCpu->cpum.s.GuestMsrs.msr.TscAux = uValue; 92 | } 93 | 94 | + 95 | +//Allow to read LSTAR MSR 96 | +VMMR0_INT_DECL(uint64_t) CPUMR0GetGuestMsrLSTAR(PVMCPU pVCpu) 97 | +{ 98 | + uint64_t tmp = myMsrLSTAR; 99 | + myMsrLSTAR = 0; 100 | + return tmp; 101 | +} 102 | + 103 | + 104 | + 105 | #endif /* IN_RING0 */ 106 | diff -bur VirtualBox-4.3.12-orig/src/VBox/VMM/VMMR0/HMVMXR0.cpp VirtualBox-4.3.12/src/VBox/VMM/VMMR0/HMVMXR0.cpp 107 | --- VirtualBox-4.3.12-orig/src/VBox/VMM/VMMR0/HMVMXR0.cpp 2014-05-16 14:27:27.000000000 +0200 108 | +++ VirtualBox-4.3.12/src/VBox/VMM/VMMR0/HMVMXR0.cpp 2014-07-20 07:29:30.124092866 +0200 109 | @@ -1864,7 +1864,9 @@ 110 | hmR0VmxSetMsrPermission(pVCpu, MSR_IA32_SYSENTER_CS, VMXMSREXIT_PASSTHRU_READ, VMXMSREXIT_PASSTHRU_WRITE); 111 | hmR0VmxSetMsrPermission(pVCpu, MSR_IA32_SYSENTER_ESP, VMXMSREXIT_PASSTHRU_READ, VMXMSREXIT_PASSTHRU_WRITE); 112 | hmR0VmxSetMsrPermission(pVCpu, MSR_IA32_SYSENTER_EIP, VMXMSREXIT_PASSTHRU_READ, VMXMSREXIT_PASSTHRU_WRITE); 113 | - hmR0VmxSetMsrPermission(pVCpu, MSR_K8_LSTAR, VMXMSREXIT_PASSTHRU_READ, VMXMSREXIT_PASSTHRU_WRITE); 114 | + //hmR0VmxSetMsrPermission(pVCpu, MSR_K8_LSTAR, VMXMSREXIT_PASSTHRU_READ, VMXMSREXIT_PASSTHRU_WRITE); 115 | + //Intercept read and write on LSTAR 116 | + hmR0VmxSetMsrPermission(pVCpu, MSR_K8_LSTAR, VMXMSREXIT_INTERCEPT_READ, VMXMSREXIT_INTERCEPT_WRITE); 117 | hmR0VmxSetMsrPermission(pVCpu, MSR_K6_STAR, VMXMSREXIT_PASSTHRU_READ, VMXMSREXIT_PASSTHRU_WRITE); 118 | hmR0VmxSetMsrPermission(pVCpu, MSR_K8_SF_MASK, VMXMSREXIT_PASSTHRU_READ, VMXMSREXIT_PASSTHRU_WRITE); 119 | hmR0VmxSetMsrPermission(pVCpu, MSR_K8_KERNEL_GS_BASE, VMXMSREXIT_PASSTHRU_READ, VMXMSREXIT_PASSTHRU_WRITE); 120 | @@ -4070,7 +4072,10 @@ 121 | { 122 | pGuestMsr->u32Msr = MSR_K8_LSTAR; 123 | pGuestMsr->u32Reserved = 0; 124 | + pGuestMsr->u64Value = CPUMR0GetGuestMsrLSTAR(pVCpu); 125 | + if(pGuestMsr->u64Value == 0){ 126 | pGuestMsr->u64Value = pMixedCtx->msrLSTAR; /* 64 bits mode syscall rip */ 127 | + } 128 | pGuestMsr++; cGuestMsrs++; 129 | pGuestMsr->u32Msr = MSR_K6_STAR; 130 | pGuestMsr->u32Reserved = 0; 131 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include