明輝手游網(wǎng)中心:是一個免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺!

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

[摘要]需求監(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知識。