Friend of mine got a new laptop from the company he works for. The laptop is really good: SSD, quad core i5.. much better than any computer he own and its with him all them time. The logical thing to do is use it as a personal computer as well, but he can't as he doesn't have any permissions on the Windows 7 installed and he does not want to accidently crash to death the company Windows 7 with his personal computer uses. The solution? Installing windows on portable USB disk. Actually not that easy because windows requires driver to the disk controller, a problematic thing with usb storage. There is a Microsoft solution to the problem called Windows To Go and with it I installed windows 8.1 portable on USB disk, which in the laptop can be boot using the bios boot menu and choosing the windows usb drive.
First problem solved, not that difficult because of Microsoft solution. Second problem came as my friend is working with his portable windows, but someone called from work and want something checked, that can only be checked using the company windows 7. The only way he can switch to the company windows 7 is by resetting the entire computer, not a convenient thing to do. My solution to the problem was to boot the company windows 7 using Vmware, telling Vmware to boot from physical disk. Shortly after boot, blue screen
07b windows error is related to boot disk controller not being recognized. The error actually makes sense because the native disk controller of the laptop is probably SATA AHCI and the Vmware disk controller is LSI SAS, and windows can't boot because of this. In the case of Windows 7 solving it is easy because Windows 7 got built in driver to support LSI SAS but it is not enabled by default. In order to enable it you need to change some key in the registry:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LSI_SAS
But to change that value you need administrative permission, which I don't have. The logical thing to do in this situation was to mount the disc using the portable windows, loading the registry hive, and changing the key. This solution is not possible in our case because the disk is fully encrypted and the company Windows 7 is loaded with a driver that opens it on the fly meaning I can't mount it!
Windows 7 recovery does not work as well, because it does not load the encryption drivers. This is going to be problematic.
After some thinking the only way I found to solve this problem is debugging Vmware itself. I started searching the internet and found really cool way to debug the guest that vmware runs, it called guest debugging and its a hidden feature in vmware that can be enabled using this option in the VMX:
debugStub.listen.guest32 = "TRUE" # for 32 bit
or
debugStub.listen.guest64 = "TRUE" # for 64 bit
From my reading I saw that other virtualization softwares also allow this.
This feature will open gdbserver on the Vmware host, attaching to it will debug the guest VM.
The gdb server will debug your guest from the first bios instruction up to your kernel and apps.
Exactly what I needed!
What do we do from now? what are we debugging?
There is a nice Hex-Rays guide which explain how to debug windows kernel using this method. This korean post explain the changes to x64 debugging and I used this script to actually find the kernel base instead of Hex-Rays way. Now debugging, my logic told me, start the VM, waits for windows loading screen (just before the blue-screen),attach the debugger, debug the registry access to LSI_SAS and change it, at this point the kernel should boot. After some debugging and playing with kernel I realized how I was wrong. I studied more about the boot process of windows and came to the conclusion that when I am debugging ntoskrnl.exe it already too late. Let me explain about the windows boot process:
credit to: bandwidthco
Shortly: The bios call MBR, MBR is calling BOOTMGR (can be found in C:\ or C:\Windows\Boot), calling winload.exe and then calling the ntoskrnl.exe. Why is it important? because ntoskrnl does not load its own boot drivers, and does not enumerate over the services registry keys,
it is winload.exe!
Winload contains function named CmpFindDriver
As you can see this function open the services registry keys as sorted array and by their subkeys determine if to load it or not. Knowing the LSI_SAS index in the registry I can put a conditional breakpoint (R13 is the registry index) and load it into the driver array. First we need the find the winload address, for this we need to get a little bit backward from winload. I boot the vm and attach to it. I load the bootmgr pdb symbol at its fixed location located at 0x0x400000. I break on _Archx86TransferTo64BitApplicationAsm
Single stepping this function will eventually jump to winload OslMain function. The OslMain is at 0x1000 offset from the winload start address, loading there the pdb file. Now we can debug winload. Setting the conditional breakpoint in CmpFindDriver and changing how the winload access the registry allow me to inject LSI_SAS driver to ntoskrnl and boot the system!!
It's not over yet, it is far from over actually. Now the windows has booted up, but I do not want to jump start the windows 7 with debugger every time I want to start the VM, I need permanent solution to change the registry, I need administrator rights. I found this post about hooking lsass ValidatePassword function in order to gain privileges. I need to get from vmware gdbserver to the lsass process, but how?
The address of the kernel I debugging is virtual. I can't access lsass virtual memory because its not mapped to my kernel virtual memory. I need to debug windows process context manager, and watch when the windows is switching to lsass, then inside the lsass context I can debug the lsass itself.
Understanding the context manager:
I need to find who is changing the cr3 register, which is responsible for virtual address mapping. I found kernel function named KiAttachProcess which changes the cr3 register:
I need to place conditional breakpoint here, but I don't know what the cr3 register should be in the case of lsass. This kind of information is stored in the kernel memory, I can parse it myself in IDA but it's time consuming. I decided to use vmss2core, dump to windbg core file and let windbg parse it:
DirBase is the condition we need to set in the breakpoint
The address we need to hook.
I also ran mimikatz but it was really a long shot.
Back to our context manager, after the conditional breakpoint we are in lsass context. I want to debug the PasswordValidate, but the memory is not mapped. It turns out that if the lsass never accessed this function it will not be mapped, and I think that I cannot place breakpoints on an unmapped memory address. I need lsass calling this function at least one time for it to mapped. Run as user with random password fixed it and the memory was mapped. I can now hook the lsass functions and gain admin rights!
All of this was working on my testing environment, the real test was my friend laptop. The driver loading was working right away and the windows booted. The mimikatz did not really get anything special (as expected). The real disappointment was that the lsass hook did not work in friend laptop because there was no local admin user and the domain was inactive and failed the authentication (even if the domain was active it might not work). It also possible that a strong policy is forbidding even administrators to make registry changes for example. But! it turns out that changing the winload access to the registry changed it somehow permanently, and after restart everything is working, I don't know how but it's working!
Despite everything is working correctly I still wanted to solve the admin right thing in a domain environment. In this windows rootkit article I found several ways to gain privileges, one of them was to copy the token from the _EPROCESS struct of system to my cmd which was working under my test environment and I hoping is working too under a domain controlled windows too.
That's it for now,
Thanks for reading!
This comment has been removed by a blog administrator.
ReplyDelete