⬆️ ⬇️

We study the MMP protocol (Mail.ru agent) and write an alternative client

It's no secret that Mail.ru Agent has become quite a popular IM project. Here you and support for ICQ, XMPP, voice calls and even sending SMS, only now the company Mail.ru completely forgot about the developers.

The official documentation of the Mail.ru Data Exchange Protocol Agent describes the protocol version 1.7 implemented in 2008. At the moment the server uses protocol version 1.24.



A bit of theory



At first glance, writing a network client is nothing complicated, but there are many “pitfalls” in network programming. Without understanding the details of how TCP / IP works, it’s almost impossible to write an effective and stable application.



Data integrity


As you know, TCP is a streaming protocol, and although data is transmitted in IP packets, the packet size is not directly related to the amount of data transmitted by TCP. Therefore, it is impossible to say with confidence that when calling recv we will get the specified number of bytes.

To get data of a given length, I use this function

#define SEND 0 #define RECV 1 int (__stdcall *tcp_func)(SOCKET s,char* buf,int len,int flags); //   /    len int tcp_rs(unsigned char type,SOCKET s, void *buf, int len, int flags) { int total = 0; int n; *(void* *)&tcp_func=(type==SEND)?&send:&recv; while(total < len) { n = tcp_func(s, (char *)buf+total, len-total, flags); if(n>0) { total += n; } else if(n == 0) { closesocket(s); return 0; } else { n=WSAGetLastError(); closesocket(s); return (!n+1); } } return total; } 


which, if successful, returns the number of received / transmitted bytes equal to len, 0 if the connection was terminated or closed, and (minus) the error number if the call to the send / recv function fails.



Network outages


It is also necessary to remember that TCP does not poll the connection. In the case of blocking sockets, if the server crashes (disconnection, failure), we will wait for a response “forever”, the program will simply “hang”.

One way to determine if a connection is broken is a keep-alive timer.

 #define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4) #pragma pack(push,1) //   typedef struct tcp_keepalive { DWORD onoff; DWORD keepalivetime; DWORD keepaliveinterval; } tcp_keepalive; #pragma pack(pop) //     keep-alive struct tcp_keepalive alive; DWORD dwSize; alive.onoff = 1; alive.keepalivetime = 5000; alive.keepaliveinterval = 1000; WSAIoctl(my_sock, SIO_KEEPALIVE_VALS, &alive, sizeof(alive),NULL, 0, &dwSize, NULL, NULL); 


In our case, if the connection is not active for 5 seconds, a service message will be sent, if there is no answer to it, the connection will be closed.

')

About protocol



MMP binary asynchronous protocol. Binary means that data is transmitted in the form of packets of a certain structure:

 //   typedef struct mrim_packet_header_t { unsigned int magic; // Magic unsigned int proto; //   unsigned int seq; // Sequence unsigned int msg; //   unsigned int dlen; //   unsigned int from; //   unsigned int fromport; //   unsigned char reserved[16]; //  } mrim_packet_header_t; //    ,   MFC, Delphi  typedef struct LPS { unsigned int len; unsigned char *str; } LPS; 


Asynchrony here is characterized by the fact that the server, maintaining a constant connection at different time intervals, sends data packets to the client, having received which the client can (and in some cases should) respond and send a response to the server.



The client initializes the connection, before this it is necessary to get the address of the “free” MMP server in text format ip: port , simply by connecting to mrim.mail.ru. The official client version 5.9 uses the following ports for connection: 2024, 80, 5190, 1863, 25, 110, 443.

As stated in the official documentation, after connecting to the recommended address, the client must send the package MRIM_CS_HELLO, wait for MRIM_CS_HELLO_ACK, then send the authorization package, then the most interesting begins.



In fact


Starting with version 1.22 (Mail.ru agent 5.7), the authorization method has changed. Now for authorization you need to send a package 0x1078 (MRIM_CS_LOGIN3) with parameters



LPS ## login ## login user email

LPS ## md5 password ## password encrypted in md5

Ffffffff

and 1391 bytes identifying the Mail.ru client



At the moment (protocol version 1.24) the protocol supports mandatory encryption. After receiving the MRIM_CS_HELLO_ACK packet, the client sends the 0x1086 packet and receives the 0x1087 response, after which the SSL connection is initialized.

But so far no one forbids us to use earlier versions of the protocol.



An important feature of the client’s work is that the client can send its requests only after receiving the package MRIM_CS_CONTACT_LIST2 from the server, which in turn is sent after successful authorization.



Projects



All the client's MMP code would take up a lot of space, so I suggest you download and study it yourself. The archive MMPclient_sample.25.04.2011.rar , are the source code in the C language and the project Visual Studio.

UPD: source on github



To study the protocol was written by a small SOCKS 5 server. It allows you to track the message chain of the client and the server in a convenient way. Server sources and project can be downloaded here.



And:



Links



All versions of Mail.ru Agent

Official protocol documentation



Tutorial games on WINSOCK

Detecting a broken TCP connection

Efficient TCP / IP programming

Source: https://habr.com/ru/post/136041/



All Articles