Mysql Protocol sniffing and mysql Protocol sniffing
Requirement
Monitors all the mysql traffic of the network card for resolution. You can perform intrusion detection (IDS) or data integration without affecting existing services.
Key points of the agreement
At first, it was found that the data packet format was different when mysql-front was used to access the database and the mysql client was used to access the database. The data packet format was long and hard to understand. the mysql-front source code looked at it and delphi didn't understand it.
Compression Parsing
If the-C parameter is enabled when mysql is connected, compression is enabled for connection data. The compression format is zlib.
The compression function of mysql is:
1 // mysql-source/mysys/my_compress.c 2 3 my_bool my_compress(uchar *packet, size_t *len, size_t *complen) 4 { 5 DBUG_ENTER("my_compress"); 6 if (*len < MIN_COMPRESS_LENGTH) 7 { 8 *complen=0; 9 DBUG_PRINT("note",("Packet too short: Not compressed"));10 }11 else12 {13 uchar *compbuf=my_compress_alloc(packet,len,complen);14 if (!compbuf)15 DBUG_RETURN(*complen ? 0 : 1);16 memcpy(packet,compbuf,*len);17 my_free(compbuf);18 }19 DBUG_RETURN(0);20 }21 22 23 uchar *my_compress_alloc(const uchar *packet, size_t *len, size_t *complen)24 {25 uchar *compbuf;26 uLongf tmp_complen;27 int res;28 *complen= *len * 120 / 100 + 12;29 30 if (!(compbuf= (uchar *) my_malloc(key_memory_my_compress_alloc,31 *complen, MYF(MY_WME))))32 return 0; /* Not enough memory */33 34 tmp_complen= (uint) *complen;35 res= compress((Bytef*) compbuf, &tmp_complen, (Bytef*) packet, (uLong) *len);36 *complen= tmp_complen;37 38 if (res != Z_OK)39 {40 my_free(compbuf);41 return 0;42 }43 44 if (*complen >= *len)45 {46 *complen= 0;47 my_free(compbuf);48 DBUG_PRINT("note",("Packet got longer on compression; Not compressed"));49 return 0;50 }51 /* Store length of compressed packet in *len */52 swap_variables(size_t, *len, *complen);53 return compbuf;54 }
The35Line callsCompress ()Function, but only compress () is encapsulated, and there is no protocol parsing part. Let's continue.
It is difficult to find the target code for the entire project. You can first find the key information in the header file, so you find the following code
// mysql-source/include/sql_state.h
{ ER_NET_UNCOMPRESS_ERROR ,"08S01", "" }
This is when mysql parses the compressed data, if the error message and error code are prompted, it can search for its reference in sequence and find the real data packet compression code.
1 // mysql-source/sql/net_serv.cc 2 3 static uchar * 4 compress_packet(NET *net, const uchar *packet, size_t *length) 5 { 6 uchar *compr_packet; 7 size_t compr_length; 8 const uint header_length= NET_HEADER_SIZE + COMP_HEADER_SIZE; 9 10 compr_packet= (uchar *) my_malloc(key_memory_NET_compress_packet,11 *length + header_length, MYF(MY_WME));12 13 if (compr_packet == NULL)14 return NULL;15 16 memcpy(compr_packet + header_length, packet, *length);17 18 /* Compress the encapsulated packet. */19 if (my_compress(compr_packet + header_length, length, &compr_length))20 {21 /*22 If the length of the compressed packet is larger than the23 original packet, the original packet is sent uncompressed.24 */25 compr_length= 0;26 }27 28 /* Length of the compressed (original) packet. */29 int3store(&compr_packet[NET_HEADER_SIZE], static_cast<uint>(compr_length));30 /* Length of this packet. */31 int3store(compr_packet, static_cast<uint>(*length));32 /* Packet number. */33 compr_packet[3]= (uchar) (net->compress_pkt_nr++);34 35 *length+= header_length;36 37 return compr_packet;38 }
From lines 8 to 19, we can see that the group package process for data compression is added separatelyNET_HEADER_SIZE + COMP_HEADER_SIZELong Control Field
Find the macro and find its definition as follows:
1 // mysql-source/include/mysql_com.h2 3 /* Constants when using compression */4 #define NET_HEADER_SIZE 4 /* standard header size */5 #define COMP_HEADER_SIZE 3 /* compression header extra size */
Length in the NET_HEADER_SIZE field the length of the field when the data part is not decompressed
The COMP_HEADER_SIZE field is used to store the length of the extracted data. We can apply for memory in sequence and then call zlib to parse the compressed content.
If zlib Parsing is directly performed on the data captured by wireshark without analysis, the decompression fails due to the existence of the control field. The following error is reported in python:
Traceback (most recent call last): File "<stdin>", line 1, in <module>zlib.error: Error -3 while decompressing data: incorrect data check
At first, I had a headache and didn't want to look at the zlib parsing details. I found this article from mysql. Now I can record that the character string starting with zlib is often \ x78 \ x9c, if the same error occurs, check whether it is correct.