#!/usr/bin/python # Last Modified: June 22, 2003 # Written by Mike Mintz # This software is public domain. # This script has only been tested with Python 2.2 but should work in any # version 2.0 or newer. You can download Python at # To configure, either set the ACCOUNT, PASSWD, and VERSION variables, or # uncomment the raw_input lines below. Upon execution, this script will login to # the specified account up to and including the final USR. # After login, you may type text to be sent as raw protocol. To send, terminate # with an EOF character (ctrl+D). You may send commands with newlines. Note that # on my platform, ctrl+D won't work unless preceded by a newline. To cancel # everything typed since the last packet was sent, press ctrl+C followed by # ctrl+D. To exit, press ctrl+C twice in a row. # Challenges are automatically replied to, even in switchboard mode. # Upon a server RNG or XFR to SB, the script will automatically login to the SB # and switch focus to it. When the switchboard connection is closed, focus will # return to the NS. # You may utilize the built-in "m" command in the SB. The first parameter is the # TrID and the second is the ack-type. This will automatically calculate message # length and send a real MSG. In addition, all literal \r (slash R) strings are # converted to carriage returns, and all literal \n strings are ignored (because # real newlines should be utilized). Real carriage returns are ignored. import sys import select import socket import string import md5 import getpass ######### Console Color Codes ################################################## ######### If these are displayed as garbage, uncomment the last line. ########## WHITE = chr(27) + '[37;1m' CYAN = chr(27) + '[36;1m' GREEN = chr(27) + '[32;1m' PURPLE = chr(27) + '[35;1m' BLACK = chr(27) + '[30;1m' RED = chr(27) + '[31;1m' YELLOW = chr(27) + '[33;1m' BLUE = chr(27) + '[34;1m' GRAY = chr(27) + '[30;1m' #WHITE,CYAN,GREEN,PURPLE,BLACK,RED,YELLOW,BLUE,GRAY = ('',) * 9 ######### Set the following lines to the login account and VER string. ######### ACCOUNT = 'example@passport.com' PASSWD = 'mypassword' VERSION = 'MSNP2' ######## Uncomment the following lines to prompt for login information. ######## #ACCOUNT = raw_input(CYAN + 'ENTER ACCOUNT NAME: ' + WHITE) #PASSWD = getpass.getpass(CYAN + 'ENTER PASSWORD:' + WHITE) #VERSION = raw_input(CYAN + 'ENTER PROTOCOL VERSION: ' + WHITE) def get_ip_from_ds(): DS = socket.socket(socket.AF_INET, socket.SOCK_STREAM) DS.connect(('messenger.hotmail.com', 1863)) print CYAN + ' * CONNECTED TO DS' + WHITE print 'VER 0 MSNP2' + BLUE + '\\n\n' + WHITE DS.send('VER 0 MSNP2\n') print 'USR 1 MD5 I a@b.c' + BLUE + '\\n\n' + WHITE DS.send('USR 1 MD5 I a@b.c\n') data_ver = DS.recv(1024) print GREEN + data_ver.replace('\r', BLUE + '\\r' + WHITE).replace('\n', BLUE + '\\n\n' + GREEN) + WHITE data_usr = DS.recv(1024) print GREEN + data_usr.replace('\r', BLUE + '\\r' + WHITE).replace('\n', BLUE + '\\n\n' + GREEN) + WHITE DS.close() (ip, port) = string.split(string.split(data_usr)[3], ':') return (ip, int(port)) def switchboard(situation, ip, salt): print CYAN + ' * CONNECTING TO SB' + WHITE SB = socket.socket(socket.AF_INET, socket.SOCK_STREAM) SB.connect((ip, 1863)) print CYAN + ' * CONNECTED TO SB' + WHITE if situation == 'xfr': print 'USR 0 ' + ACCOUNT + ' ' + salt + BLUE + '\\n\n' + WHITE SB.send('USR 0 ' + ACCOUNT + ' ' + salt + '\n') elif situation == 'rng': print 'ANS 0 ' + ACCOUNT + ' ' + salt + BLUE + '\\n\n' + WHITE SB.send('ANS 0 ' + ACCOUNT + ' ' + salt + '\n') while 1: readable = select.select([sys.stdin, SB, NS], [], [], 1)[0] if readable.count(sys.stdin): data = sys.stdin.read() if data[:2] == 'm ': trid = string.split(data)[1] ack_type = string.split(data)[2] content = string.join(string.split(data, '\n')[1:], '\n').replace('\\r', '\r').replace('\\n', '') print '\n\n' + GRAY + 'MSG ' + trid + ' ' + ack_type + ' ' + str(len(content)) + '\n' + content + WHITE SB.send('MSG ' + trid + ' ' + ack_type + ' ' + str(len(content)) + '\n' + content) else: SB.send(data) if readable.count(SB): try: data = SB.recv(8192) except: print CYAN + ' * SB SOCKET ERROR' + WHITE break if not data: print CYAN + ' * SB DISCONNECTED' + WHITE break print PURPLE + data.replace('\r', BLUE + '\\r' + WHITE).replace('\n', BLUE + '\\n\n' + GREEN) + WHITE cmd = data[0:3] parameters = string.split(data[3:]) if cmd == 'VER': pass if readable.count(NS): try: data = NS.recv(8192) except: print CYAN + ' * SOCKET ERROR' + WHITE sys.exit(0) if not data: print CYAN + ' * DISCONNECTED' + WHITE sys.exit(0) print GREEN + data.replace('\r', BLUE + '\\r' + WHITE).replace('\n', BLUE + '\\n\n' + GREEN) + WHITE cmd = data[0:3] parameters = string.split(data[3:]) if cmd == 'CHL': qry_to_send = 'QRY 666 msmsgs@msnmsgr.com 32\n' + md5.new(parameters[1] + 'Q1P7W2E4J9R8U3S5').hexdigest() print qry_to_send.replace('\r', BLUE + '\\r' + WHITE).replace('\n', BLUE + '\\n\n' + GREEN) + WHITE NS.send(qry_to_send) print CYAN + ' * CONNECTING TO DS' + WHITE NS = socket.socket(socket.AF_INET, socket.SOCK_STREAM) NS.connect(get_ip_from_ds()) print CYAN + ' * CONNECTED TO NS' + WHITE print 'VER 0 ' + VERSION + BLUE + '\\n\n' + WHITE NS.send('VER 0 ' + VERSION + '\n') def ns_process(): readable = select.select([sys.stdin, NS], [], [], 1)[0] if readable.count(sys.stdin): NS.send(sys.stdin.read()) if readable.count(NS): try: data = NS.recv(8192) except: print CYAN + ' * SOCKET ERROR' + WHITE sys.exit(0) if not data: print CYAN + ' * DISCONNECTED' + WHITE sys.exit(0) print GREEN + data.replace('\r', BLUE + '\\r' + WHITE).replace('\n', BLUE + '\\n\n' + GREEN) + WHITE cmd = data[0:3] parameters = string.split(data[3:]) if cmd == 'VER': print 'USR 1 MD5 I ' + ACCOUNT + BLUE + '\\n\n' + WHITE NS.send('USR 1 MD5 I ' + ACCOUNT + '\n') elif cmd == 'USR' and parameters[1] == 'MD5': usr_to_send = 'USR 2 MD5 S ' + md5.new(parameters[3] + PASSWD).hexdigest() + '\n' print usr_to_send NS.send(usr_to_send) elif cmd == 'CHL': qry_to_send = 'QRY 666 msmsgs@msnmsgr.com 32\n' + md5.new(parameters[1] + 'Q1P7W2E4J9R8U3S5').hexdigest() print qry_to_send.replace('\r', BLUE + '\\r' + WHITE).replace('\n', BLUE + '\\n\n' + GREEN) + WHITE NS.send(qry_to_send) elif cmd == 'XFR': ip = string.split(parameters[2], ':')[0] salt = parameters[4] switchboard('xfr', ip, salt) elif cmd == 'RNG': ip = string.split(parameters[1], ':')[0] salt1 = parameters[3] salt2 = parameters[0] switchboard('rng', ip, salt1 + ' ' + salt2) while 1: try: ns_process() except KeyboardInterrupt: try: sys.stdin.read() print '\n' + CYAN + 'Input Buffer Reset' + WHITE + '\n' except KeyboardInterrupt: print '\n' + CYAN + 'USER EXIT' + WHITE + '\n' sys.exit(0) # EOF