#!/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