[转帖]Mysql 协议嗅探_MySQL, Oracle及数据库讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  MySQL, Oracle及数据库讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 1778 | 回复: 0   主题: [转帖]Mysql 协议嗅探        上一篇   下一篇 
ad222888
注册用户
等级:新兵
经验:66
发帖:134
精华:0
注册:2016-9-25
状态:离线
发送短消息息给ad222888 加好友    发送短消息息给ad222888 发消息
发表于: IP:您无权察看 2019-8-29 9:08:05 | [全部帖] [楼主帖] 楼主

需求

监听通过网卡的所有mysql流量,进行解析,可在不影响现有业务情况下,进行入侵检测(IDS)或数据集成

协议要点
起初发现 用mysql-front访问数据库和mysql 的客户端访问时数据包格式不同,纠结很久,不明白,mysql-front源码看了眼,delphi,不懂,弃

压缩解析
当链接mysql时,若启用-C参数表示,对于连接数据启用压缩,压缩格式为zlib

mysql的压缩函数为:

1 // mysql-source/mysys/my_compress.c
3 my_bool my_compress(uchar *packet, size_t *len, size_t *complen)
5 DBUG_ENTER("my_compress");
6 if (*len < MIN_COMPRESS_LENGTH)
8 *complen=0;
9 DBUG_PRINT("note",("Packet too short: Not compressed"));
11 else
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);
19 DBUG_RETURN(0);
23 uchar *my_compress_alloc(const uchar *packet, size_t *len, size_t *complen)
25 uchar *compbuf;
26 uLongf tmp_complen;
27 int res;
28 *complen= *len * 120 / 100 + 12;
30 if (!(compbuf= (uchar *) my_malloc(key_memory_my_compress_alloc,
31 *complen, MYF(MY_WME))))
32 return 0; /* Not enough memory */
34 tmp_complen= (uint) *complen;
35 res= compress((Bytef*) compbuf, &tmp_complen, (Bytef*) packet, (uLong) *len);
36 *complen= tmp_complen;
38 if (res != Z_OK)
40 my_free(compbuf);
41 return 0;
44 if (*complen >= *len)
46 *complen= 0;
47 my_free(compbuf);
48 DBUG_PRINT("note",("Packet got longer on compression; Not compressed"));
49 return 0;
51 /* Store length of compressed packet in *len */
52 swap_variables(size_t, *len, *complen);
53 return compbuf;
54 }


其中第35行调用了zlib中的compress()函数,但是该处仅对compress()进行了封装,并没有协议解析部分,我们继续往下看。

整个项目寻找目标代码比较费劲,可以先在头文件中寻找关键信息,于是找到了下面的代码

// mysql-source/include/sql_state.h
{ ER_NET_UNCOMPRESS_ERROR ,"08S01", "" }


这是在mysql在解析压缩的数据时如果出错的提示信息和错误码,依次可以查找其引用,发现了真正的数据包压缩代码

1 // mysql-source/sql/net_serv.cc
3 static uchar *
4 compress_packet(NET *net, const uchar *packet, size_t *length)
6 uchar *compr_packet;
7 size_t compr_length;
8 const uint header_length= NET_HEADER_SIZE + COMP_HEADER_SIZE;
10 compr_packet= (uchar *) my_malloc(key_memory_NET_compress_packet,
11 *length + header_length, MYF(MY_WME));
13 if (compr_packet == NULL)
14 return NULL;
16 memcpy(compr_packet + header_length, packet, *length);
18 /* Compress the encapsulated packet. */
19 if (my_compress(compr_packet + header_length, length, &compr_length))
21 /*
22 If the length of the compressed packet is larger than the
23 original packet, the original packet is sent uncompressed.
24 */
25 compr_length= 0;
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++);
35 *length+= header_length;
37 return compr_packet;
38 }


从8-19行可以看到,压缩数据的组包过程,前面分别加了NET_HEADER_SIZE + COMP_HEADER_SIZE 长的控制字段

查找该宏,发现其定义如下

1 // mysql-source/include/mysql_com.h
3 /* Constants when using compression */
4 #define NET_HEADER_SIZE 4 /* standard header size */
5 #define COMP_HEADER_SIZE 3 /* compression header extra size */


COMP_HEADER_SIZE字段是用来存储解压后的包长度的,我们可以依次申请内存,然后调用zlib对压缩内容进行解析即可。

如果不分析直接进行对wireshark抓到的数据进行zlib解析的话,由于控制字段的存在会解压缩失败,在python中的报错如下

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
zlib.error: Error -3 while decompressing data: incorrect data check


起初看到这个错误很头痛也不想看zlib解析细节,才有了从mysql找原因的本文,现在可以记录zlib 压缩字符串的开头常常是\x78\x9c,出现同样错误的可以看看是否正确




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论