Since March 10, 2003 - Version 2
hypothetic.org

MSN Messenger Protocol

Home Page

Forum
Chat

About

Resources

Research

Documentation
 General
 Notification
 Switchboard
 Protocols
 Reference

Validate XHTML
Validate CSS
Research - MSNP8
Printable Version

Overview

MSNP8 is a new protocol that was introduced with MSN Messenger 5. The following description of the protocol has been somewhat peer-reviewed and tested, but may still contain omissions or errors. Please contact us if you find anything wrong with this page.

Bitwise Programming Functions

In order to implement MSNP8, you need to use the "bitwise AND" function in a couple of places. Unlike the "logical AND" used in conditional statements, "bitwise AND" manipulates numbers on a binary level - it's almost impossible to guess what's going on just by looking at the decimal output. To work out what a binary AND does, break the numbers you're ANDing into a sum of powers of 2. The output of a bitwise AND is the sum of the powers of 2 which appear in both input numbers. For example, 11 is 8+2+1, and 7 is 4+2+1, so a bitwise AND on 11 and 7 will return 3 (2+1).

Different programming languages use different symbols to represent "bitwise AND" - consult your documentation to find out what it is in your language. This site will use "AND", so "3 AND 2" means "do a bitwise AND on the numbers 3 and 2".

Authentication

Clients that support MSNP8 must also support the CVR0 protocol. The CVR command must be sent immediately after the VER command to a notification server. The format of the CVR command has also changed slightly in MSNP8 - you must now send a string as the eighth argument to the CVR command. The official client sends your passport, but the server is just as happy if you send something else, like "null". The format of the CVR reply has not changed.

The INF command, which was optional in MSNP7, no longer exists in MSNP8. If you attempt to send it while logging in, you will be immediately disconnected.

The format of the USR command is almost unchanged in MSNP8, but MD5 authentication has been abandoned in favour of TWN ("Tweener") authentication, which is based on Passport authentication, discussed below. If you try to use MD5 authentication, you will be immediately disconnected by the server. The final USR reply from the server now includes an extra numerical argument at the end, which may be related to the extra numerical arguments discussed in status messages, below.

When a client authenticates with MS Passport, it is given a "ticket". This ticket is passed back to the notification server in the final USR reply.

Putting an example of an MSNP8 login on this page would cause horizontal scrolling, so please see the authentication example page.

Passport Authentication

Passport Authentication is Microsoft's attempt to provide a "single sign-on" system for all Internet services, from Messenger to online banking. Some background information about it is available on MSDN, but this page assumes no knowledge of passport.

Authentication with MS Passport involves sending HTTPS requests to Microsoft's Passport servers in order to retrieve a passport "ticket", which is then sent to the server you really want to connect to. HTTPS is HyperText Transfer Protocol encrypted using "Secure Sockets Layer". It is recommended that you find a library for your chosen programming language that supports HTTPS - even if you choose to write your own HTTP parser, you should not try to implement SSL (it's far too complex and security-sensitive to implement as part of a larger project).

Passport servers allow you to either send your login details as an HTML file in the body of the request or as headers of the HTTPS request itself. The "HTML" method is only intended for use by web browsers, but will work fine for MSN Messenger clients. The "header" method is recommended for Messenger clients, and is the only method explained on this site. The passport authentication process involves the following steps:

  1. The client (optionally) connects to the Passport "Nexus", and retrieves the URL of a login server. This result doesn't change very often, so it can be cached.
  2. The client authenticates itself with this login server. The server will do one of:
    • Redirect the client to another login server for the client to authenticate with (note: this server must not be cached).
    • Report a failure in the login process, with an appropriate error message.
    • Return a "ticket". This ticket is sent back to the notification server in the USR reply.

Connecting to the Nexus involves sending an HTTPS GET request for the URL "https://nexus.passport.com/rdr/pprdr.asp". The Nexus allows you to use HTTPS version 1.0. The server should always reply with a 200 OK message with an empty body. The important information is contained in the "PassportURLs" header, which contains a comma-separated list. The "DALogin" field of this header contains the address of the login server. This value isn't technically a valid URL, so your HTTPS library might require you to add "https://" to the start of it.

The client should then send an HTTPS GET request for the URL given to it by the Nexus. Login servers require you to use HTTPS version 1.1. The request should include an "Authorization" header, which is made up of a preamble ("Passport1.4 OrgVerb=GET,OrgURL=http%3A%2F%2Fmessenger%2Emsn%2Ecom"), your URL-encoded passport, password, and the challenge string given to you by the Notification Server.

The server's response should be either a 200 OK message (for success), 302 Found (for redirection) or 401 Unauthorized (for failure). The message will contain either an "Authentication-Info" or a "WWW-Authenticate" header. It's not known why two different header names are used, although at present "WWW-Authenticate" is only used with failed logins. It's safest to assume that the two header names are interchangeable. The header will contain a "da-status" field of "success", "failed" or "redir" (redirect). If the response is a redirection, there will also be a "Location" header, which includes the URL the client is being redirected to.

If the response is a failure, the header will include a "cbtxt" field, which contains a URL-encoded error message, and a "cburl" header that contains the URL of a picture you might want to display along with it.

If the response is a redirection, the "Location" field will contain the URL of another Login Server. At the time of writing, the client will be redirected if it has a passport that ends in "@hotmail.com" or "@msn.com". The client must begin the login step again.

If the response is a success, the "Authentication-Info" header will include a "from-PP" field, which contains the ticket to return to the Notification Server. This field has a slightly unusual format, in that the value is inside apostrophes and includes several equals signs (but no commas).

Example session

Because passport authentication involves very long strings, it causes horizontal scrolling when displayed on this site, so please see the authentication example page.

Initial Profile

The initial text/x-msmsgsprofile message sent by the server has gained two fields and lost one. The "LoginTime" field no longer exists - you should record your system's idea of UNIX time instead. Also, the "ClientIP" and "ClientPort" fields have been added to the end of the message. These tell the client about the IP address and source port the server believes the client is connecting from. The source port for a connection is the port on the client computer, whereas the destination port (usually 1863 in MSN Messenger sessions) is the port the server listens on. Unfortunately, a bug in the MSN Messenger server mangles the "ClientPort" value, and you need to do some work to get the actual port number.

The technical term is that the value has been "byte-swapped", and an explanation of what exactly has happened is beyond the scope of this page. There are several ways to get the correct number back, but the recommended method is to calculate ((ClientPort AND 255) * 256) + ((ClientPort AND 65280) / 256) - there are neater ways to write that function, but they would take a much deeper understanding of binary arithmetic to explain. An alternative is to use a function called ntohc, but this function doesn't exist in all programming languages, and doesn't work on all hardware architectures (for example, it won't work on Apple computers).

The client port and IP address can be used to guess whether the connection to the server is going through some kind of network address translation ("NAT") or proxy server. In MSNP8, this information is only used to decide the value of the "Connectivity" field during file transfer, but more advanced handling of this information - this is covered on the MSNP9 page.

Here is an example message, where the client's actual source port is 1025:

MSG Hotmail Hotmail 432\r\n
MIME-Version: 1.0\r\n
Content-Type: text/x-msmsgsprofile; charset=UTF-8\r\n
EmailEnabled: 1\r\n
MemberIdHigh: 84352\r\n
MemberIdLow: 1317109683\r\n
lang_preference: 1033\r\n
preferredEmail: \r\n
country: UK\r\n
PostalCode: \r\n
Gender: \r\n
Kid: 0\r\n
Age: \r\n
BDayPre: \r\n
Birthday: \r\n
Wallet: \r\n
Flags: 1031\r\n
sid: 507\r\n
kv: 5\r\n
MSPAuth: 4sCuECZ4UsAaBIy0AIsk!c9bWcuATTmuQ$$\r\n
ClientIP: 81.99.77.64\r\n
ClientPort: 260\r\n
\r\n

Status messages

The CHG, ILN and NLN, but not FLN commands now have a an extra numerical argument at the end. This argument represents some kind of client ID structuce, which is discussed more in the client ID page.

Clients set their version number with the CHG command, which will then be passed to other clients along with ILN and NLN notifications. If you leaving the extra parameter out of a CHG, the server will set your version number to 0.

Here is an example CHG with no extra parameter:

>>> CHG 12 NLN\r\n

<<< CHG 12 NLN 0\r\n

Here is an example CHG with a version number of 500:

>>> CHG 12 NLN 500\r\n

<<< CHG 12 NLN 500\r\n

And an example ILN:

<<< ILN 12 AWY example@passport.com Mike 268435492\r\n

Contact list synchronisation

Microsoft were presumably pressured to reduce the time it took to log into MSN Messenger, as the SYN command has been overhauled to minimise bandwidth. When the cached version of the contact list is the same as the version on the server, the response is just the same as it was in MSNP7, but when the cached version is out-of-date, the response is very different. Note that the change of format for many responses only applies to the SYN command - responses to other commands (e.g. ADD) are the same as in MSNP7.

The initial SYN response will contain a TrID and one or three parameters.

  • The first parameter is the list version number. If this is the same as the version number sent by the client, there will be no more parameters.
  • The second parameter is the number of LST responses to expect.
  • The third parameter is the number of LSG responses to expect.

Next, GTC and BLP responses will be received. Neither has a TrID or list version number.

If you have any personal phone numbers, PRPs will be sent next. Blank phone numbers will not be sent, neither will "MOB" or "MBE" if their value is "N". They include just two parameters:

  • The first parameter is the type of phone number (PHH etc.)
  • The second parameter is the phone number itself

Then the group list is sent by the server. These no longer have a TrID, list version number, incrementing number or total number.

Next, the user list and phone numbers are sent by the server. The format of this has changed totally from MSNP7.

The new LST response lists each user once in total (instead of once for every list they appear in), and includes three or four parameters (and no TrID):

  • The first parameter is the user's passport
  • The second parameter is the user's friendlyname
  • The third parameter is a numerical value representing the lists the user is in (their "list number").
  • The fourth parameter (if the user is on your FL) is a list of groups they belong to.

Each list has a numerical value, and a user's list number represents the sum of the lists the user is in. The FL's value is 1, the AL is 2, the BL is 4 and the RL is 8. So, someone on your FL and AL but not your BL or RL would have a list number of 3.

Programming note: it's easiest to separate out the lists a user belongs to with the "bitwise AND" function. Doing a bitwise AND between a user's list number and a list value will return the list value if the user is on that list, or zero otherwise. For example, if someone's list number is 11, you can check whether they are on your AL by doing "11 AND 2", which will return 2. Similarly, checking whether they are on your BL with "11 AND 4" will return 0.

BPR responses are sent immediately after the user they apply to, and are formatted identically to PRPs.

Here is an example SYN response:

>>> SYN 1 0\r\n

<<< SYN 1 139 5 4\r\n

<<< GTC A\r\n
<<< BLP AL\r\n

<<< PRP PHH 01%20234\r\n
<<< PRP PHM 56%20789\r\n

<<< LSG 0 Other%20Contacts 0\r\n
<<< LSG 1 Coworkers 0\r\n
<<< LSG 2 Friends 0\r\n
<<< LSG 3 Family 0\r\n

<<< LST user1@passport.com user1 4\r\n
<<< LST user2@passport.com user2 10\r\n
<<< LST user3@passport.com user3 11 0,1,2,3\r\n
<<< LST user4@passport.com user4 11 0\r\n
<<< BPR PHH 01%20234\r\n
<<< BPR MOB Y\r\n
<<< LST user5@passport.com user5 12\r\n

Challenges

CHLs needn't change from MSNP7, but more information about CHL strings has been found during the analysis of clients that support MSNP8. The client's QRY includes a string that was previously thought to always be "msmsgs@msnmsgr.com". In fact, it turns out that different Microsoft-registered clients send different strings here, and have appropriately different hashes. An alternative is to use "PROD0038W!61ZTF9" instead of "msmsgs@msnmsgr.com" and "VT6PX?UQTM4WM%YR" instead of "Q1P7W2E4J9R8U3S5".

E-mail invitations

The SDC command has been changed in MSNP8. It can now be sent at any time, not just ofter a FND (which no longer works for any protocol version). It takes a TrID and eight parameters:

  • The first parameter is the the e-mail address you want to send a message to.
  • The second, third, fourth, fifth and sixth parameters are "0x0409 MSNMSGR MSMSGS X X"
  • The seventh argument is the name in the subject line ("<name> wants to talk to you!") of the e-mail they receive.
  • The eighth argument is the length of the payload to this command.

For example, if I wanted to contact someone with the address "example@passport.com", I might send the following:

>>> SDC 3 example@passport.com 0x0409 MSMSGS WindowsMessenger X X Andrew%20Sayers 8\r\n
    Hi Mike! (no newline)

If the message was successfully sent, the server will return an SDC response with a TrID and a single parameter of "OK":

<<< SDC 21 OK\r\n

Copyright ©2002-2003 to Mike Mintz.