As you might have heard, Microsoft recently patched some vulnerabilities; vulnerabilities related to Sandworm CVE-2014-4114 (Powerpoint exploit) and font parsing (CVE-2014-4148). But in this article, I'm more interested to talk about CVE-2014-4113, which is a local kernel vulnerability that successful exploitation would give you SYSTEM access. So I started analyzing patch (KB3000061) and mid-analysis, I found a PoC for this vulnerability in the wild. Therefore I combined my patch analysis and reverse engineering of PoC binary together to deeply understand this vulnerability and exploitation technique. Here, I'll share it step by step, with all details, so you'll know everything about CVE-2014-4113.
Knowing this, I started to think about exploitation method of this vulnerability, how to trigger this vulnerability and make xxxHandleMenuMessages API to call xxxSendMessage with an invalid HANDLE. As soon as I saw that the vulnerability is related to window system and possible NULL value during xxxHandleMenuMessage process, I just remembered this. For exploiting that, you had to map zero/null page, create a fake object at zero page and trigger the vulnerability. So this was the general idea, now I had to find a way to trigger this vulnerability by causing xxxHandleMenuMessage call xxxSendMessage with a NULL handle. Luckily I suddenly saw that there is a PoC published online for this vulnerability, so as a lazy person, instead of trying to solve it on my own as a practice/challenge, I just downloaded the sample and started to analyze it. Lots of things was as I thought, the only missing part in chain of exploitation was how to make that NULL in xxxHandleMenuMessage. It was done by hooking and altering parameters in user mode, you can read more about these tricks here and here.
Cyan color holds address of shellcode and yellow background holds WS_EXECUTE_IN_KERNEL flag.
That was it. Using this simple hooking and altering popup menu, kernel will call and execute callback function at null page, in kernel space. I think I've said enough about this bug. So please update your OS, specially servers, as soon as possible, because lowest access (for example ASP.NET shell with ASP.NET user account) can get SYSTEM access using this vulnerability.
Excellent post, you write very good and detailed. Please keep it up.
Nice post, just a question.
Nice post, just a question. You said using ZwAllocateVirtualMemory you can map zero page and reason for this is "16-bit application support", can you explain this a little more?
16-bit support in modern windows systems are done by NTVDM. NTVDM, in order to implement kernel mode INT10 Video API (see this) which modifies value in zero page, needs to map the zero page. Therefore Windows have to allow this null page mapping.
I like your blog and your posts, I really do, just sometimes I don't like software you use for the job. For example, why Turbodiff? Why not DarunGrim, BinDiff, Patchdiff?
Your write is very special. everything clear and understood.
I have a question. I guess you are wrong regarding ZwAllocateVirtualMemory().
A pointer to a variable that will receive the base address of the allocated region of pages. If the initial value of this parameter is non-NULL, the region is allocated starting at the specified virtual address rounded down to the next host page size address boundary. If the initial value of this parameter is NULL, the operating system will determine where to allocate the region.
According to MSDN, if you provide BaseAddress as 0x0, Windows will decide where to allocate the memory. I have reversed the exploit and, they too are not using BaseAddress as 0x0 instead, they are using 0x1.
Thank you for reading the article carefully, yes, you are definitely right, I fixed article accordingly. You need to pass 0x01 to map null page.
Thanks for your comment and I should say I totally agree. Token offset was hardcoded based on Windows version, cached reference to system token can (even though rare) case BSOD and use of bunch of global variables in the PoC doesn't seem to be a good idea. I think sample PoC, as it's name says, was just "proof-of-concept". So it did the job as "proof-of-concept", but definitely it wasn't most efficient code to exploit this vulnerability.
I do not understand something.
Weakness occurs when not checked the returns -5 (0xFFFFFFFb) and pass it to function xxxSendMessage.
According to the first image (Vulnerable win32k.sys) actually seems that ensure that the value -5 inserted.