Mysql 協(xié)議嗅探是什么

需求

監(jiān)聽通過網(wǎng)卡的所有mysql流量,進行解析,可在不影響現(xiàn)有業(yè)務(wù)情況下,進行入侵檢測(ids)或數(shù)據(jù)集成

協(xié)議要點

起初發(fā)現(xiàn) 用mysql-front訪問數(shù)據(jù)庫和mysql 的客戶端訪問時數(shù)據(jù)包格式不同,糾結(jié)很久,不明白,mysql-front源碼看了眼,delphi,不懂,棄

壓縮解析

當鏈接mysql時,若啟用-C參數(shù)表示,對于連接數(shù)據(jù)啟用壓縮,壓縮格式為zlib

mysql的壓縮函數(shù)為:

//?mysql-source/mysys/my_compress.c    my_bool?my_compress(uchar?*packet,?size_t?*len,?size_t?*complen)  {  ??DBUG_ENTER("my_compress");  ??if?(*len?=?*len)  ??{  ????*complen=?0;  ????my_free(compbuf);  ????DBUG_PRINT("note",("Packet?got?longer?on?compression;?Not?compressed"));  ????return?0;  ??}  ??/*?Store?length?of?compressed?packet?in?*len?*/  ??swap_variables(size_t,?*len,?*complen);  ??return?compbuf;  }

?其中第35行調(diào)用了zlib中的compress()函數(shù),但是該處僅對compress()進行了封裝,并沒有協(xié)議解析部分,我們繼續(xù)往下看。

整個項目尋找目標代碼比較費勁,可以先在頭文件中尋找關(guān)鍵信息,于是找到了下面的代碼

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

這是在mysql在解析壓縮的數(shù)據(jù)時如果出錯的提示信息和錯誤碼,依次可以查找其引用,發(fā)現(xiàn)了真正的數(shù)據(jù)包壓縮代碼

//?mysql-source/sql/net_serv.cc    static?uchar?*  compress_packet(NET?*net,?const?uchar?*packet,?size_t?*length)  {  ??uchar?*compr_packet;  ??size_t?compr_length;  ??const?uint?header_length=?NET_HEADER_SIZE?+?COMP_HEADER_SIZE;    ??compr_packet=?(uchar?*)?my_malloc(key_memory_NET_compress_packet,  ????????????????????????????????????*length?+?header_length,?MYF(MY_WME));    ??if?(compr_packet?==?NULL)  ????return?NULL;    ??memcpy(compr_packet?+?header_length,?packet,?*length);    ??/*?Compress?the?encapsulated?packet.?*/  ??if?(my_compress(compr_packet?+?header_length,?length,?&amp;compr_length))  ??{  ????/*  ??????If?the?length?of?the?compressed?packet?is?larger?than?the  ??????original?packet,?the?original?packet?is?sent?uncompressed.  ????*/  ????compr_length=?0;  ??}    ??/*?Length?of?the?compressed?(original)?packet.?*/  ??int3store(&amp;compr_packet[NET_HEADER_SIZE],?static_cast<uint>(compr_length));  ??/*?Length?of?this?packet.?*/  ??int3store(compr_packet,?static_cast<uint>(*length));  ??/*?Packet?number.?*/  ??compr_packet[3]=?(uchar)?(net-&gt;compress_pkt_nr++);    ??*length+=?header_length;    ??return?compr_packet;  }</uint></uint>

?從8-19行可以看到,壓縮數(shù)據(jù)的組包過程,前面分別加了NET_HEADER_SIZE + COMP_HEADER_SIZE 長的控制字段

查找該宏,發(fā)現(xiàn)其定義如下

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

NET_HEADER_SIZE 字段中 長度字段存儲 數(shù)據(jù)部分 未解壓時的長度

COMP_HEADER_SIZE 字段是用來存儲 ?解壓后的 數(shù)據(jù)的長度,我們可以依次申請內(nèi)存,然后調(diào)用zlib對壓縮內(nèi)容進行解析即可。

?如果不分析直接進行對wireshark抓到的數(shù)據(jù)進行zlib解析的話,由于控制字段的存在會解壓縮失敗,在python中的報錯如下

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

?起初看到這個錯誤很頭痛也不想看zlib解析細節(jié),才有了從mysql找原因的本文,現(xiàn)在可以記錄zlib 壓縮字符串的開頭常常是x78x9c,出現(xiàn)同樣錯誤的可以看看是否正確

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點贊13 分享