wireshark原始碼分析

來源:互聯網
上載者:User

各位親,不是我不想回複你們的問題。是我也不瞭解。不能誤導。希望大家相互協助。看看能否幫那些提問的小盆友們回複一下呢。

這些都是轉載的,如果實在沒有辦法,可以開啟連結到原作者哪裡去提問試試看。。。



經過多次嘗試,終於在windows上成功編譯wireshark原始碼,但用的不是下面的這個步驟,不過大同小異,我的是vs2005,所以用的:http://blog.csdn.net/alexander_vc/article/details/6198836 的方法。 1.2.7版的wireshark的capture_if_details_dlg_win32.c對vs2005有bug,需要下載更新的wireshark版本,並更換該檔案。詳見wireshark的Wireshark Bug Database – Bug 3439


幾點注意:1.python要用2.4——2.6版本

                    2.Cygwin安裝要把文中介紹的庫一併安裝

                    3.如果執行命令,總是nmake報各種錯,請反覆檢查你的Wireshark目錄裡面config.nmake檔案配置的是否正確。


用vs2005,vs2010都編譯成功了。不得不說這得靠人品,多試試,辦法總是有的。


原文地址:http://blog.sina.com.cn/xianjiaotonguniversity
在windows上編譯wireshark原始碼

在編譯過程中需要以下軟體:VisualStudio,Python,Cygwin以及Wireshark原始碼。

1. Visual Studio

我使用的是Visual Studio 2008版本。

2. Python

下載安裝Python,從2.4 –2.6應該都是可以的,我使用2.6版本。主要是在編譯過程中會使用到Python。

3. Cygwin

去Cygwin上下載最新版本安裝,然後開始安裝,整個安裝過程是線上安裝,特別注意的是,以下庫必須安裝,否則不能順利完成編譯:

Archive / unzipDevel / bisonDevel / flexInterpreters / perlUtils / patchWeb / wget

4. 下載Wireshark原始碼 &編輯config.nmake

輸入這個網址,http://www.wireshark.org/download/src/all-versions/,從上面下載Wireshark原始碼,這裡,值得一提的是,最好下載頁面中給出的svn中的原始碼,能保證該代碼絕對是最新的。

下載完成之後,在Wireshark目錄裡面開啟config.nmake,需要進行一些設定之後才可以開始編譯。

(1)WIRESHARK_LIBS, 設定編譯wireshark所需的庫所在的目錄,預設即可。
(2)PROGRAM_FILES,設定本機程式安裝目錄,預設即可。
(3)MSVC_VARIANT,因為我使用VS2008編譯,所以這裡不要修改。如果使用的是其他版本的VS,則要將相應行前面的#去掉,並把其餘行的#加上。例如如果你使用的是VS2005,則將值為MSVC2005的那一行前的#去掉,其餘MSVC_VARIANT項行首全部加上#注釋掉。
(4)CYGWIN_PATH,將其設定為cygwin的bin目錄,例如D:\cygwin\bin。
(5)MSVCR_DLL,如果VS安裝在D盤,請在這裡相應的地方用絕對路徑表示,而不要去修改前面的PROGRAM_FILES,否則會出現意想不到的錯誤。

5. 編譯Wireshark

用VS2008安裝的VS2008命令提示進入或者通過CMD進入之後,再去運行VC下面的vcvars32.bat,或者是把vcvars32.bat拖到命令視窗,再斷行符號就行。然後進去Wireshark目錄,首先通過下面的命令檢驗一下:

nmake -f Makefile.nmake verify_tools得到的資訊如下:我忘了截圖,這是copy別人的圖,不過我的跟他的基本一樣,出了上面的著作權資訊是中文,以及著作權資訊下面有個Error,說是C:\wireshark-win32-libs\current_tag.txt中的內容應該是2011-06-27外,其他都是一樣的。不過這個錯誤不用管,不會影響編譯。
6.執行nmake –f Makefile.nmake setup得到很多資訊,最後如下:7.先執行下nmake –f Makefile.nmake distclean8.執行nmake –f Makefile.nmake all 這個過程要花上10幾分鐘,到這裡,編譯就完成了。


wireshark原始碼分析報告之一 因為手頭的項目需要識別應用程式層協議,於是想到了wireshark,打算在項目中整合wireshark協議分析代碼。在官網上下了最新版的wireshark原始碼,我的天啊,200多M,這麼多代碼檔案怎麼看。在網上了找了很久,希望能找到別人的分析報告,可惜的是,找了很久也沒有找到,比較多的還是怎麼開發wireshark協議識別和分析外掛程式,很少有人分析它的原始碼。於是,我找了個查看原始碼比較方便的工具——sourceinsight,打算先瞧一瞧這些代碼檔案,說不定運氣好,看著看著就知道它是怎麼工作的。

   看過wireshark原始碼的人應該知道,它的代碼檔案很多很多,而我也是第一次閱讀別人這麼多的代碼,所以要把wireshark的協議分析代碼整合到我的項目中,對我來說還真不是一件容易的事。花了很多時間,搜了很多資料,也看了很多資料,最後決定從wireshark的命令列模式——tshark入手,分析tshark是如何識別網路通訊協定的。

   我決定利用斷點調試查看tshark是如何工作的,但是要調試,就需要編譯串連wireshark原始碼。於是又開始找資料摸索怎麼編譯我wireshark代碼。這部分的資料倒是比較好找,但是當時找的資料都不能順利編譯,最後在別人的基礎上,加上自己的思考,終於編譯成功。於是就有了上一篇文章描述如何在visual studio2008上編譯wireshark原始碼。

   囉嗦了這麼多,真正開始分析tshark代碼了。

   首先,成功編譯後的wireshark原始碼檔案夾中出現了很多目標檔案,還產生了一個wireshark-gtk2檔案夾,裡面有好幾個exe檔案,比如wireshark.exe,tshark.exe,dumpcap.exe等。具體如下所示:




  這個圖片就是wireshark-gtk2檔案夾中的一部分。

   接下來,可以用visualstudio2008(工具不限制,但最後是跟你編譯時間選定的工具保持一致)開啟wireshark-gtk2所在目錄下的工程檔案,這樣的工程檔案有好幾個,隨便開啟一個,其他的幾個就會自動添加進來,因為所有的工程檔案都在一個解決方案中,如下圖所示:



   因為只分析tshark部分的代碼,所以可以把它之外的工程全部刪除,然後在tshark工程源檔案中有一個tshark.c的檔案,在裡面找到main()函數,這就是程式的入口,這時就可以下斷點跟蹤調試了。

   今天先寫到此,明天再附上詳細的分析報告。


wireshark原始碼分析報告之二

一、原始碼結構

在wireshark原始碼根目錄下,可以看到以下子目錄:

1)物理結構


   其中,epan檔案夾負責所有網路通訊協定識別工作,plugins裡面存放了wireshark所有外掛程式,gtk檔案夾裡面是wireshark的介面部分代碼,其餘檔案夾沒有單獨研究。

2)邏輯結構

   下圖給出了Ethereal功能模組:   a) GTK1/2

      處理使用者的輸入輸出,源碼在gtk目錄    b) Core

      將其他模組串連在一起,源碼在根目錄   c) Epan

      Ethereal Packetage Analyzing,包分析引擎,源碼在epan目錄

 l Protocol-Tree:儲存資料包的協議資訊

 l Dissectors:在epan/dissector目錄下,各種協議解碼器

 l Plugins:一些協議解碼器以外掛程式形式實現,源碼在plugins目錄

 l Display-Filters:顯示過濾引擎,源碼在epan/dfilter目錄   d) Capture

  捕包引擎

    e) Wiretap

      從檔案中讀取資料包,支援多種檔案格式,源碼在wiretap目錄



二、Tshark協議解析模組

主要處理流程如下所示:

第一步: 

cf_status_t cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err):

      該函數首先調用wtap* wtap_open_offline (const char *filename, int *err, char **err_info,gboolean do_random) 函數,獲得一個wtap struct。

wtap結構體的定義在wiretap目錄下的Wtap-int.h

struct wtap {
    FILE_T            fh;
    FILE_T            random_fh;    /* Secondary FILE_T for random access */
    int            file_type;
    guint            snapshot_length;
    struct Buffer        *frame_buffer;
    struct wtap_pkthdr    phdr;
    union wtap_pseudo_header pseudo_header;

    gint64            data_offset;
    void            *priv;

    subtype_read_func    subtype_read;
    subtype_seek_read_func    subtype_seek_read;
    void            (*subtype_sequential_close)(struct wtap*);
    void            (*subtype_close)(struct wtap*);
    int            file_encap;    /* per-file, for those file formats that have per-file encapsulation types */
    int            tsprecision;    /* timestamp precision of the lower 32bits * e.g. WTAP_FILE_TSPREC_USEC */

    wtap_new_ipv4_callback_t add_new_ipv4;
    wtap_new_ipv6_callback_t add_new_ipv6;
    GPtrArray *fast_seek;
};

a) wtap_open_offline() 函數的處理流程: 調用int libpcap_open(wtap *wth, int *err, gchar **err_info)函數讀取給定pcap 檔案的檔案頭資訊,總共 28 個位元組,如下所示:

 檔案頭結構體
 sturct pcap_file_header
 {
      DWORD           magic;//4個位元組
      WORD           version_major;//主要版本號,通常為2
      WORD           version_minor;//副版本號碼,通常為4
      DWORD           thiszone;
      DWORD           sigfigs;
      DWORD           snaplen;
      DWORD           linktype;
 } 

libpcap_open() 函數首先讀取magic資訊,如果檔案沒有被修改,則繼續讀取檔案頭的後續資訊。讀取整個檔案頭資訊後,判斷該資訊是否合法,如果合法,再嘗試讀取給定pcap檔案的前2個資料包的包頭記錄,這個工作通過調用static libpcap_try_t libpcap_try(wtap *wth, int *err)函數完成。

libpcap_try()函數首先調用libpcap_read_header()函數讀取第一個資料包的資料包頭,該資料包頭的結構如下所示:

struct pcap_pkthdr
{
struct tim         ts;
      DWORD              caplen;//所捕獲資料包儲存在pcap檔案中的實際長度,以位元組為單位。
      DWORD              len;//所捕獲的資料包的真實長度。
}
 
struct tim
{
DWORD       GMTtime;//捕獲資料包的時間,從格林尼治時間的1970年1月1日00:00:00到抓包時經過的秒數。
DWORD       microTime;//抓取資料包時的微秒值。

該資料包頭總共16個位元組。然後再調用file_seek()(該函數主要功能就是實現檔案定位)函數定位到第一個資料包之後,即24位元組的檔案頭+16位元組的資料包頭+caplen位元組的第一個資料包的資料部分長度。如果file_seek()操作正確,即不返回-1,則libpcap_try()函數再次調用libpcap_read_header()函數,讀取第二個資料包的包頭資訊。如果讀取正確,則libpcap_try()函數返回THIS_FORMAT,表示pcap檔案格式正確。

這時libpcap_open()調用file_seek()定位到給定pcap檔案的檔案頭之後,也就是24位元組處,並返回1,表示操作成功。

 

b)wtap_open_offline()函數為wtap的frame_buffer結構體的buffer部分分配最大空間1500位元組,然後返回給定pcap檔案的wtap資訊。

 

c)當wtap_open_offline()函數正確返回wtap資訊後,cf_open()函數調用cleanup_dissection()函數清空接下來在協議解析工作中需要用到的資料結構。 cleanup_dissection() 的清空工作包括:

          1) conversation(epan_conversation_cleanup());

          2) circuits(epan_circuit_cleanup());

          3) protocol-specific variables(g_slist_foreach(init_routines, &call_init_routine, NULL));

          4) stream-handling tables(stream_cleanup());

          5) expert infos(expert_cleanup())。 cleanup_dissection() 返回後, cf_open() 函數調用 init_dissection() 函數初始化後續解析工作中要用到的所有資料。init_dissection() 的初始化工作基本上與 cleanup_dissection() 清空的內容一致。 這些工作完成後,設定capture_file資訊並返回到main() 函數。

 

2. 設定時間精度

 

3. static int load_cap_file(capture_file *cf, char *save_file, int out_file_type, gboolean out_file_name_res, int max_packet_count, gint64 max_byte_count)函數載入給定的pcap檔案。

load_cap_file()函數完成的具體工作如下:

a) 如果save_file(儲存捕獲的資料包資訊)參數不為空白,則調用wtap_dump_open()函數擷取wtap_dump結構體。

b) 調用gboolean wtap_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)函數讀取給定pcap檔案資料。

c) 調用wtap結構中的subtype_read指向的函數,即libpcap_read()函數,讀取下一個資料包資料。這部分的處理流程類似於第一階段的cf_open()中的處理方式,也就是libpcap_read()函數調用libpcap_read_header()函數讀取下一個資料包16個位元組的包頭部分,具體讀取16位元組包頭的工作由libpcap_read_header()函數調用file_read()完成。

d) 如果libpcap_read_header()操作正確,成功返回讀取的資料包位元組數,則libpcap_read()函數調整檔案指標位移量,然後調用pcap_process_pseudo_header()函數處理該資料包的pseudo_header資訊,主要是確定FCS的長度。(pseudo翻譯成"虛假的,假冒的",可能是有些資料包有些假冒包頭吧,不是很瞭解。)然後返回pseudo_header的長度。

e) Libpcap_reader()函數根據返回的pseudo_header長度,調整資料包的實際長度,以及檔案的位移量,具體操作是:

   

              orig_size -= phdr_len;//phdr_len is the length of pseudo_header.

              packet_size -= phdr_len;

              wth->data_offset += phdr_len;

f) Libpcap_read()函數調用buffer_assure_space()函數確保wtap結構中的frame_buffer中分配的空間足夠容納正在讀取的資料包的大小,如果不夠,則需要把frame_buffer中已經用掉的空間中存放的內容移到frame_buffer的前面,然後在分配1024個位元組給frame_buffer,並返回。

g) Libpcap_read()函數調用libpcap_read_rec_data()函數讀取改資料包的資料部分,具體的讀取工作同樣由file_read()函數完成。

h) 調整檔案位移量,更新timestamp,調用pcap_read_post_process()函數,根據wtap_encap值,確定pseudo_header的eth.fcs_len的大小。

i) Libpcap_read()工作完成,返回到wtap_read(),如果libpcap_read()返回true,wtap_read()也返回true。

j) 調用static gboolean process_packet(capture_file *cf, gint64 offset, const struct wtap_pkthdr *whdr, union wtap_pseudo_header *pseudo_header, const guchar *pd, gboolean filtering_tap_listeners, guint tap_flags)函數處理前面讀取的資料包內容。具體操作如下:

i. Process_packet()函數調用frame_data_init()函數初始化該資料包的幀資料結構,包括記錄資料包頭資訊等。如果需要解析資料包,在判斷是否需要建立協議樹(列印協議詳細資料),接著調用epan_dissect_t* epan_dissect_init(epan_dissect_t *edt, const gboolean create_proto_tree, const gboolean proto_tree_visible)函數完成解析前的初始化工作。在epan_dissect_init()函數中,如果create_proto_tree為真,就調用protp_tree_create_root()函數建立協議樹的根節點,並賦值為edt->tree,並且,調用proto_tree_set_visible()設定該協議樹的可見度為proto_tree_visible參數的值。如果create_proto_tree為假,則edt->tree=NULL;返回edt。至此,epan_dissect_init()的工作完成

ii. 接著,判斷是否設定有讀過濾器,即capture_file結構體的rfnode是否為空白。如果不為空白,就調用epan_dissect_prime_dfilter(&edt, cf->rfnode)進行處理(具體處理過程還沒跟蹤調試。)。

iii. 調用void col_custom_prime_edt(epan_dissect_t *edt, column_info *cinfo)函數(這個函數具體任務不確定)。如果沒有使用者自訂的列印內容,則直接返回;否則要根據使用者設定,進行一些操作。

iv. 調用void tap_queue_init(epan_dissect_t *edt)函數初始化tap queue。

v. 調用frame_data_set_before_dissect()函數進行解析前的幀資料設定作業。

具體內容包括:

1)設定第一個包和前一個包的時間戳記。如果first_ts未設定,則表示當前的包是第一個資料包,則把first_ts設為第一個資料包的時間;如果prev_cap_ts未設定,也表明當前的資料包是第一個資料包,則也把它設為第一個包的時間,即frame_data結構體的abs_ts屬性。

2)計算當前資料包接收時間與第一個資料包接收時間之差。

3)計算前一個資料包已經被列印的資料包的接收時間與當前資料包的接收時間之差。如果前一個被列印的資料包的接收時間沒有設定,則表示在當前資料包之前,還沒有資料包被列印。這個時候,就把前一個被列印資料包的接收時間設為0;否則計算這個差值。

4)計算前一個資料包的捕捉時間與當前資料包的捕捉時間之差,並儲存到frame_date的del_cap_ts屬性中。

5)以上4步完成之後,把前一個資料包的捕捉時間設為當前資料包的捕捉時間, 返回到process_packet()。

vi. 調用void epan_dissect_run(epan_dissect_t *edt, void* pseudo_header, const guint8* data, frame_data *fd, column_info *cinfo)函數開始真正的解析工作。該函數的處理過程大致如下所示:

a) 調用ep_free_all()函數釋放前一個資料包中的解析工作中分配的所有記憶體。

b) 調用void dissect_packet(epan_dissect_t *edt, union wtap_pseudo_header *pseudo_header, const guchar *pd, frame_data *fd, column_info *cinfo)函數進行解析。

具體操作為:

1)如果

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.