Mysql 協(xié)議嗅探是什么
發(fā)表時間:2023-07-18 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]需求監(jiān)聽通過網(wǎng)卡的所有mysql流量,進(jìn)行解析,可在不影響現(xiàn)有業(yè)務(wù)情況下,進(jìn)行入侵檢測(IDS)或數(shù)據(jù)集成協(xié)議要點(diǎn)起初發(fā)現(xiàn) 用mysql-front訪問數(shù)據(jù)庫和mysql 的客戶端訪問時數(shù)據(jù)包格式不...
需求
監(jiān)聽通過網(wǎng)卡的所有mysql流量,進(jìn)行解析,可在不影響現(xiàn)有業(yè)務(wù)情況下,進(jìn)行入侵檢測(IDS)或數(shù)據(jù)集成
協(xié)議要點(diǎn)
起初發(fā)現(xiàn) 用mysql-front訪問數(shù)據(jù)庫和mysql 的客戶端訪問時數(shù)據(jù)包格式不同,糾結(jié)很久,不明白,mysql-front源碼看了眼,delphi,不懂,棄
壓縮解析
當(dāng)鏈接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 < MIN_COMPRESS_LENGTH)
{
*complen=0;
DBUG_PRINT("note",("Packet too short: Not compressed"));
}
else
{
uchar *compbuf=my_compress_alloc(packet,len,complen);
if (!compbuf)
DBUG_RETURN(*complen ? 0 : 1);
memcpy(packet,compbuf,*len);
my_free(compbuf);
}
DBUG_RETURN(0);
}
uchar *my_compress_alloc(const uchar *packet, size_t *len, size_t *complen)
{
uchar *compbuf;
uLongf tmp_complen;
int res;
*complen= *len * 120 / 100 + 12;
if (!(compbuf= (uchar *) my_malloc(key_memory_my_compress_alloc,
*complen, MYF(MY_WME))))
return 0; /* Not enough memory */
tmp_complen= (uint) *complen;
res= compress((Bytef*) compbuf, &tmp_complen, (Bytef*) packet, (uLong) *len);
*complen= tmp_complen;
if (res != Z_OK)
{
my_free(compbuf);
return 0;
}
if (*complen >= *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()進(jìn)行了封裝,并沒有協(xié)議解析部分,我們繼續(xù)往下看。
整個項(xiàng)目尋找目標(biāo)代碼比較費(fèi)勁,可以先在頭文件中尋找關(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, &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(&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->compress_pkt_nr++);
*length+= header_length;
return compr_packet;
}
從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)容進(jìn)行解析即可。
如果不分析直接進(jìn)行對wireshark抓到的數(shù)據(jù)進(jìn)行zlib解析的話,由于控制字段的存在會解壓縮失敗,在python中的報(bào)錯如下
Traceback (most recent call last):
File "<stdin>", line 1, in <module>zlib.error: Error -3 while decompressing data: incorrect data check
起初看到這個錯誤很頭痛也不想看zlib解析細(xì)節(jié),才有了從mysql找原因的本文,現(xiàn)在可以記錄zlib 壓縮字符串的開頭常常是\x78\x9c,出現(xiàn)同樣錯誤的可以看看是否正確
以上就是Mysql 協(xié)議嗅探是什么的詳細(xì)內(nèi)容,更多請關(guān)注php中文網(wǎng)其它相關(guān)文章!
學(xué)習(xí)教程快速掌握從入門到精通的SQL知識。