Windows 8 - Let It Be SMEP!


    With the advent of a new generation of Intel processors based on the Ivy Bridge architecture, a new security hardware has been introduced. It is called Intel SMEP. Like the NX bit, which prevents code from executing on a memory page, it adds a headache to exploiting kernel-mode vulnerabilities.

    In turn, Microsoft implemented SMEP support in Windows 8, thus making this OS even safer. However, the first implementation of SMEP support “head-on” turned out to be a minor flaw, thanks to which the attacker still has the possibility of exploiting vulnerabilities relatively painless for him.

    What is SMEP?


    SMEP stands for “Supervisor Mode Execution Prevention” - preventing code execution in supervisor mode. Supervisor mode is the preferred processor mode in which the kernel of Windows 8 runs. In terms of the OS, this mode is also called kernel mode. The opposite is the user mode - in this mode, user applications are executed.

    OS protection is based on the fact that user applications cannot perform privileged operations, for example, accessing I / O ports, processor control registers, etc. In addition, memory used in kernel mode is protected from user mode access. A user application cannot read, modify, or execute code directly in kernel memory. Interaction with the OS kernel occurs indirectly through the system call interface.

    Privileged mode, in turn, has no restrictions, if not for SMEP. If it is enabled, any attempt to execute the code in the memory of the user application will result in a page fault. In particular, in the page error handler on Windows 8, this situation will cause a bugcheck.
    Simply put, if any driver or system module of the kernel tries to execute the code located in the memory of the user application, it will all end with a blue screen of death with a sad emoticon.

    What's the point?


    Vulnerabilities in the kernel mode are the most “delicious” for the attacker, since upon successful operation he receives full control over the target system. The point is that when exploiting vulnerabilities in the kernel mode, an attacker, as a rule, allocates memory in user mode for storing shell code.

    “But in kernel mode, you can no longer execute code from the pages of user memory! And where is now to store the shell code? What’s the point of an attack without your own shellcode? Or maybe you don’t need to attack then? ”

    With the expectation of such an attacker’s thinking, this technology was created. It is able to protect the end user from a whole class of attacks, if you bring its implementation to mind and cover the “rear” with other defense mechanisms.



    The first pancake is lumpy


    Let's think it over. You cannot store shellcode in user space. This means that it should be located in the kernel memory (the choice is not great - there are only two modes), the contents of this memory section should be controlled by us (we cannot write directly from the user mode), and it should be possible to find out the address of this memory section from the user mode (you cannot and read from user mode directly). What can be used to deliver shellcode to the kernel?

    The most obvious solution is to use Windows objects. The ones with which applications work through descriptors (handle). These are all kinds of timers, events, mutexes, I / O completion ports, graphic objects, etc. The body of such an object is located in the kernel memory, and the contents can be changed from user mode, and we can find out at what address in the kernel space they are located!

    For example, when we open a file with the CreateFile () function, we get a handle to the open file. If the application needs to read a couple of bytes of this file into the buffer, then we call the ReadFile () function, which, using a system call, transfers control to the OS kernel, where it finds the desired file object from the descriptor table. In this case, the object is of type _FILE_OBJECT, and the variable field in it is the file name. Those. theoretically, you could create a file called "\ 0xBAADC0DE" that will contain our shellcode. Then we exploit some kernel mode vulnerability and transfer control to our shell code.

    0: kd> dt nt! _FILE_OBJECT
    + 0x000 Type: Int2B
    + 0x002 Size: Int2B
    ...
    + 0x050 Flags: Uint4B
    + 0x058 FileName: _UNICODE_STRING
    + 0x068 CurrentByteOffset: _LARGE_INTEGER
    ...
    + 0x0c0 IrpList: _LIST_ENTRY
    + 0x0d0 FileObjectExtension: Ptr64 Void

    Success? Not quite yet. The fact is that SMEP on Windows 8 is complemented by another security mechanism. Despite the fact that the code is located on the kernel mode page, this page has a mark (bit NX) that it is not executable, i.e. code cannot be executed on this page! It turns out that Windows objects are protected from execution, therefore, are also not suitable for storing shell code. This statement is true for the x64 version of Windows 8. However, in x86 versions of the body of graphic objects are located in executable memory!

    The palette turned out to be the most suitable object for delivering the shellcode. It is created using the CreatePalette () function and the LOGPALETTE structure, the contents of which are filled with shell code. Still, how to validate colors in a palette? Indeed, in our palette will be exactly the colors that we want! And we will want many bytes of NOP (0x90), and many bytes of shellcode. This is the “evil” palette ...



    So, we have the SMEP workaround for Windows 8 x86:
    1. Create the “evil” LOGPALETTE structure, filling it with shell code.
    2. Create a palette through CreatePalette ().
    3. Find the address of the palette object in the kernel through the shared GDI table.
    4. We transfer control at a certain offset from the palette object.
    5. ???????
    6. PROFIT !!!

    And what to do with x64?


    Want SMEP workaround on Windows 8 x64? I have them! Perhaps the method is not so interesting, but it’s working. SMEP on x64 is bypassed by using Return Oriented Programming (ROP). In short, ROP uses sections of code from other modules that are already present in memory. Thus, you do not need to forward your shell code to the kernel.

    Of course, the attacker's capabilities in the preparation of the payload in this case are very limited. But all that the attacker needs is to disable SMEP, and for this, the ntoskrnl module has “presents” in the form of the HvlEndSystemInterrupt () and KiConfigureDynamicProcessor () functions. The last bytes of these functions allow you to disable SMEP on a given processor.

    HvlEndSystemInterrupt():
    …
    pop     rax
    pop     rcx
    retn
    


    KiConfigureDynamicProcessor():
    …
    mov     cr4, rax
    add     rsp, 28h
    retn
    


    // ROP chain to refresh cr4 value
    //                  vTrash			vROPChain
    DWORD_PTR dwRopStack[7      +       10] = {0};
    // HvlEndSystemInterrupt gadget
    dwRopStack[7 + 0] = dwKernelBase + HvlGadgetOffset;
    // New CR4 value
    dwRopStack[7 + 1] = 0x00000000000506F8;
    // KiConfigureDynamicProcessor
    dwRopStack[7 + 3] = dwKernelBase + Cr4GadgetOffset;
    // Out address (shellcode)
    dwRopStack[7 + 9] = (DWORD_PTR)pTestBuf;
    




    Down with the restrictions


    After SMEP is disabled, the attacker is able to execute code from the user buffer, i.e. there are no more restrictions on the size of the shellcode. You can use the kernel vulnerability that was used to disable SMEP to transfer already to the "evil" shell code.

    Conclusion


    Of course, both methods are not universal. Each vulnerability has its own exploitation features. In some cases, workarounds will have to be completed, while in others they are generally not applicable.

    It is also important to understand that this is not an exploitable vulnerability in itself. This is just a method of circumventing one of the protection mechanisms, and it can only be used in tandem with some other exploitable vulnerability.

    PS SMEP is disabled by 13 bytes of code. For details, please follow the links below.
    How to beat SMEP on Windows 8 x86
    How to beat SMEP on Windows 8 x64

    Authors: Artyom Shishkin and Ilya Smith

    Also popular now: