winshark重要数据结构
說(shuō)起來(lái)有一些慚愧,研究wireshark有一段時(shí)間了,但是對(duì)源代碼的分析卻至今沒(méi)有什么進(jìn)展。。。
最初想要研究wireshark是因?yàn)槲业拈_(kāi)題是基于wireshark來(lái)做的。
現(xiàn)在有很多抓包工具,wireshark的優(yōu)勢(shì)在于完全開(kāi)源,分析功能強(qiáng)大,但其缺點(diǎn)也很明顯,即捕獲的數(shù)據(jù)包存儲(chǔ)過(guò)于分散,大數(shù)據(jù)背景下,不能有效的對(duì)海量的數(shù)據(jù)包進(jìn)行存儲(chǔ)分析,因此將wireshark捕獲到的數(shù)據(jù)存儲(chǔ)到專(zhuān)門(mén)的數(shù)據(jù)庫(kù)中是非常必要的。(當(dāng)然,存儲(chǔ)數(shù)據(jù)只是第一步,接下來(lái)還要進(jìn)行對(duì)數(shù)據(jù)的分析工作)
真正開(kāi)始分析wireshark了,首先是編譯。unbutu下很順利就編譯通過(guò)了,但是在windows下卻出現(xiàn)各種問(wèn)題,至今沒(méi)有編譯通過(guò)。。。,分析wireshark源代碼,在windows下編譯通過(guò)有必要嗎?
后來(lái)看關(guān)于wireshark的論文,接觸到了兩個(gè)東西。即winpcap、libpcap。
winpcap是底層的,在windows上wireshark是依賴于winpcap來(lái)截包的,在linux上則是依賴于libpcap。而winpcap又是基于libpcap的設(shè)計(jì)基礎(chǔ)上開(kāi)發(fā)設(shè)計(jì)的,使用方法也和libpcap基本相同。
那么,我在分析wireshark存儲(chǔ)部分源代碼的時(shí)候有必要看winpcap和libpcap的函數(shù)庫(kù)嗎?
到真正看wireshark源代碼了,200多M,算上子文件共2000多個(gè),對(duì)于一個(gè)不是計(jì)算機(jī)科班出身的我來(lái)說(shuō),不得不說(shuō),有點(diǎn)困難。。 從百度文庫(kù)上下載了些資料,主要是分析wireshark邏輯功能模塊,最有價(jià)值的應(yīng)該是這篇了,如下:
a) GTK1/2 處理用戶的輸入輸出顯示,源碼在gtk目錄.b) Core 核心模塊,通過(guò)函數(shù)調(diào)用將其他模塊連接在一起,源碼在根目錄c) Epan wireshark Packetage Analyzing,包分析引擎,源碼在epan目錄Protocol-Tree:保存數(shù)據(jù)包的協(xié)議信息,wireshark的協(xié)議結(jié)構(gòu)采用樹(shù)形結(jié)構(gòu),解析協(xié)議報(bào)文時(shí)只需要從根節(jié)點(diǎn)通過(guò)函數(shù)句柄依次調(diào)用各層解析函數(shù)即可。Dissectors:在epan/dissector目錄下,各種協(xié)議解碼器,支持700+種協(xié)議解析,對(duì)于每種協(xié)議,解碼器都能識(shí)別出協(xié)議字段(field),并顯示出字段值(field value)由于網(wǎng)絡(luò)協(xié)議種類(lèi)很多,為了使協(xié)議和協(xié)議間層次關(guān)系明顯,對(duì)數(shù)據(jù)流里的各個(gè)層次的協(xié)議能夠逐層處理,wireshark系統(tǒng)采用了協(xié)議樹(shù)的方式。Plugins:一些協(xié)議解碼器以插件形式實(shí)現(xiàn),源碼在plugins目錄Display-Filters:顯示過(guò)濾引擎,源碼在epan/dfilter目錄d) Capture 捕包引擎,利用libpcap/WinPcap從底層抓取網(wǎng)絡(luò)數(shù)據(jù)包,libpcap/WinPcap提供了通用的抓包接口,能從不同類(lèi)型的網(wǎng)絡(luò)接口(包括以太網(wǎng),令牌環(huán)網(wǎng),ATM網(wǎng)等)獲取數(shù)據(jù)包。e) Wiretap 從文件中讀取數(shù)據(jù)包,支持多種文件格式,源碼在wiretap目錄f) Win-/libpcap Wireshark抓包時(shí)依賴的庫(kù)文件wireshark功能模塊3. wireshark流程分析 1) 初始化 Wireshark的初始化包括一些全局變量的初始化、協(xié)議分析引擎的初始化和Gtk相關(guān)初始化,顯示Ethereal主窗口,等待用戶進(jìn)一步操作。重點(diǎn)就是Epan模塊的初始化。 Epan初始化:tvbuff初始化:全局變量tvbuff_mem_chunk指向用memchunk分配的固定大小的空閑內(nèi)存塊,每個(gè)內(nèi)存塊是tvbuff_t結(jié)構(gòu),從空閑內(nèi)存塊中取出后,用來(lái)保存原始數(shù)據(jù)包。協(xié)議初始化:全局變量:proto_names proto_short_names proto_filter_names 以上三個(gè)全局變量主要用來(lái)判斷新注冊(cè)的協(xié)議名是否重復(fù),如果重復(fù),給出提示信息,在協(xié)議解析過(guò)程中并沒(méi)有使用。 ? 協(xié)議注冊(cè): ? 注冊(cè)協(xié)議:將三個(gè)參數(shù)分別注冊(cè)給proto_names、proto_short_names、proto_filter_names三個(gè)全局變量中, ? 注冊(cè)字段,需要在wireshark協(xié)議樹(shù)顯示的報(bào)文內(nèi)容字段。 ? 協(xié)議解析表 ? Handoff注冊(cè) ? 將協(xié)議與父協(xié)議節(jié)點(diǎn)關(guān)聯(lián)起來(lái) ? Packet(包)初始化 ? 全局變量: ? frame_handle:協(xié)議解析從frame開(kāi)始,層層解析,直到所有的協(xié)議都解析完為止。frame_handle保存了frame協(xié)議的handle。 ? data_handle:有的協(xié)議無(wú)法從frame開(kāi)始,那么就從data開(kāi)始。原理同frame。 ? 讀配置文件preference ? 讀capture filter和display filter文件,分別保存在全局變量capture_filter和display_filter中。 ? 讀disabled protocols文件,保存全局變量global_disabled_protos和disabled_protos中 ? 初始化全局變量cfile ? Cfile是個(gè)重要的變量,數(shù)據(jù)類(lèi)型為capture file,它保存了數(shù)據(jù)包的所有信息, ? 取得命令行啟動(dòng)時(shí),參數(shù)列表,并進(jìn)行相應(yīng)的處理2) 處理流程 Wireshark初始化完成以后進(jìn)入實(shí)際處理階段,主程序創(chuàng)建抓包進(jìn)程,捕包進(jìn)程和主程序是通過(guò)PIPE進(jìn)行傳遞數(shù)據(jù)的,主程序把抓取的數(shù)據(jù)寫(xiě)入臨時(shí)文件,通過(guò)函數(shù)add_packet_to_packet_list將數(shù)據(jù)包加入包列表。處理時(shí),主程序從列表中選取一個(gè)數(shù)據(jù)包,提取該數(shù)據(jù)包中的數(shù)據(jù)填寫(xiě)在數(shù)據(jù)結(jié)構(gòu)中,最后調(diào)用協(xié)議解析函數(shù)epan_dissect_run進(jìn)行處理,從epan_dissect_run開(kāi)始,是實(shí)際的協(xié)議解析過(guò)程, 下面以HTTP協(xié)議報(bào)文為例,流程如下: a) 解析frame層 調(diào)用函數(shù)dissect_frame對(duì)frame層進(jìn)行解析,并在協(xié)議樹(shù)上填充相應(yīng)字段信息。函數(shù)最后會(huì)判斷是否有上層協(xié)議封裝,如果有則調(diào)用函數(shù)dissector_try_port在協(xié)議樹(shù)上查找對(duì)應(yīng)的解析函數(shù),這里函數(shù)dissector_try_port根據(jù)pinfo->fd->lnk_t查找對(duì)應(yīng)的上層協(xié)議處理函數(shù),pinfo->fd->lnk_t值為1,上層封裝協(xié)議為以太網(wǎng)協(xié)議,全局結(jié)構(gòu)體指針變量dissector_handle當(dāng)前的協(xié)議解析引擎句柄置為dissect_eth_maybefcs,至此,frame層解析結(jié)束。 b) 解析以太網(wǎng)層 函數(shù)call_dissector_work根據(jù)dissector_handle調(diào)用frame上層協(xié)議解析函數(shù)dissect_eth_maybefcs對(duì)以太網(wǎng)層進(jìn)行解析,并在協(xié)議樹(shù)上填充相應(yīng)字段,包括目的MAC地址和以太網(wǎng)上層協(xié)議類(lèi)型等信息。函數(shù)最后會(huì)判斷是否有上層協(xié)議封裝,如果有則調(diào)用函數(shù)dissector_try_port在協(xié)議樹(shù)上查找對(duì)應(yīng)的解析函數(shù),這里函數(shù)dissector_try_port根據(jù)etype查找對(duì)應(yīng)的上層協(xié)議處理函數(shù),以太網(wǎng)字段etype為0800的報(bào)文是ip報(bào)文,上層封裝協(xié)議為IP協(xié)議,全局結(jié)構(gòu)體指針變量dissector_handle當(dāng)前的協(xié)議解析引擎句柄置為dissect_ip,至此,以太網(wǎng)層解析結(jié)束。 c) 解析IP層 函數(shù)call_dissector_work根據(jù)dissector_handle調(diào)用以太網(wǎng)上層協(xié)議解析函數(shù)dissect_ip對(duì)以太網(wǎng)層進(jìn)行解析,并在協(xié)議樹(shù)上填充相應(yīng)字段,包括版本號(hào),源地址,目的地址等信息。函數(shù)最后會(huì)判斷是否有上層協(xié)議封裝,如果有則調(diào)用函數(shù)dissector_try_port在協(xié)議樹(shù)上查找對(duì)應(yīng)的解析函數(shù),這里函數(shù)dissector_try_port根據(jù)nxt (nxt = iph->ip_p)查找對(duì)應(yīng)的上層協(xié)議處理函數(shù),以太網(wǎng)字段nxt為06的報(bào)文是TCP報(bào)文,上層封裝協(xié)議為T(mén)CP協(xié)議,全局結(jié)構(gòu)體指針變量dissector_handle當(dāng)前的協(xié)議解析引擎句柄置為dissect_tcp,至此,IP層解析結(jié)束。 d) 解析TCP層 函數(shù)call_dissector_work根據(jù)dissector_handle調(diào)用以太網(wǎng)上層協(xié)議解析函數(shù)dissect_tcp對(duì)TCP層進(jìn)行解析,包括對(duì)TCP頭的解析和選項(xiàng)字段的解析,并在協(xié)議樹(shù)上填充相應(yīng)字段,包括源端口,目的端口,標(biāo)志位等信息。函數(shù)最后會(huì)判斷是否有上層協(xié)議封裝,如果有則調(diào)用函數(shù)dissector_try_port在協(xié)議樹(shù)上查找對(duì)應(yīng)的解析函數(shù),這里函數(shù)dissector_try_port根據(jù)port查找對(duì)應(yīng)的上層協(xié)議處理函數(shù),將源端口和目的端口分別賦值給low_port和high_port,根據(jù)low_port和high_port分別匹配上層協(xié)議解析函數(shù),port為80的報(bào)文是HTTP報(bào)文,上層封裝協(xié)議為HTTP協(xié)議,全局結(jié)構(gòu)體指針變量dissector_handle當(dāng)前的協(xié)議解析引擎句柄置為dissect_http,至此,TCP層解析結(jié)束。 e) 解析HTTP層 至此wireshark進(jìn)入應(yīng)用層協(xié)議檢測(cè)階段,wireshark解析dissect_http函數(shù)中注冊(cè)的字段,并提取相應(yīng)的字段值添加到協(xié)議樹(shù)中,應(yīng)用層的具體解析流程將在下面介紹。HTTP協(xié)議具體函數(shù)調(diào)用過(guò)程參見(jiàn): 重要的數(shù)據(jù)結(jié)構(gòu)struct _epan_dissect_t {tvbuff_t *tvb;//用來(lái)保存原始數(shù)據(jù)包proto_tree *tree;//協(xié)議樹(shù)結(jié)構(gòu)packet_info pi;// 包括各種關(guān)于數(shù)據(jù)包和協(xié)議顯示的相關(guān)信息 };/** Each proto_tree, proto_item is one of these. */ typedef struct _proto_node {struct _proto_node *first_child;//協(xié)議樹(shù)節(jié)點(diǎn)的第一個(gè)子節(jié)點(diǎn)指針struct _proto_node *last_child; //協(xié)議樹(shù)節(jié)點(diǎn)的最后一個(gè)子節(jié)點(diǎn)指針struct _proto_node *next; //協(xié)議樹(shù)節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)指針struct _proto_node *parent;//父節(jié)點(diǎn)指針field_info *finfo;//保存當(dāng)前協(xié)議要顯示的地段tree_data_t *tree_data;//協(xié)議樹(shù)信息 } proto_node;typedef struct _packet_info {const char *current_proto; //當(dāng)前正在解析的協(xié)議名稱column_info *cinfo; //wireshark顯示的信息frame_data *fd;//現(xiàn)在分析的原始數(shù)據(jù)指針union wtap_pseudo_header *pseudo_header;//frame類(lèi)型信息GSList *data_src; /*frame層信息 */address dl_src; /* 源MAC */address dl_dst; /*目的MAC */address net_src; /* 源IP */address net_dst; /*目的IP */address src; /*源IP */address dst; /*目的IP */guint32 ethertype; /*以太網(wǎng)類(lèi)型字段*/guint32 ipproto; /* IP協(xié)議類(lèi)型*/guint32 ipxptype; /* IPX 包類(lèi)型 */guint32 mpls_label; /* MPLS包標(biāo)簽*/circuit_type ctype; guint32 circuit_id; /*環(huán)路ID */const char *noreassembly_reason; /* 重組失敗原因*/gboolean fragmented; /*為真表示未分片*/gboolean in_error_pkt; /*錯(cuò)誤包標(biāo)志*/port_type ptype; /*端口類(lèi)型 */guint32 srcport; /*源端口*/guint32 destport; /*目的端口*/guint32 match_port; /*進(jìn)行解析函數(shù)匹配時(shí)的匹配端口*/const char *match_string; /*調(diào)用子解析引擎時(shí)匹配的協(xié)議字段指針*/guint16 can_desegment; /* 能否分段標(biāo)志*/guint16 saved_can_desegment; int desegment_offset; /*分段大小*/ guint32 desegment_len; guint16 want_pdu_tracking; guint32 bytes_until_next_pdu;int iplen; /*IP包總長(zhǎng)*/int iphdrlen; /*IP頭長(zhǎng)度*/int p2p_dir; guint16 oxid; /* next 2 fields reqd to identify fibre */guint16 rxid; /* channel conversations */guint8 r_ctl; /* R_CTL field in Fibre Channel Protocol */guint8 sof_eof; guint16 src_idx; /* Source port index (Cisco MDS-specific) */guint16 dst_idx; /* Dest port index (Cisco MDS-specific) */guint16 vsan; /* Fibre channel/Cisco MDS-specific *//* Extra data for DCERPC handling and tracking of context ids */guint16 dcectxid; /* Context ID (DCERPC-specific) */int dcetransporttype;guint16 dcetransportsalt; /* fid: if transporttype==DCE_CN_TRANSPORT_SMBPIPE */ guint16 decrypt_gssapi_tvb;tvbuff_t *gssapi_wrap_tvb;tvbuff_t *gssapi_encrypted_tvb;tvbuff_t *gssapi_decrypted_tvb;gboolean gssapi_data_encrypted;guint32 ppid; /* SCTP PPI of current DATA chunk */guint32 ppids[MAX_NUMBER_OF_PPIDS]; /* The first NUMBER_OF_PPIDS PPIDS which are present * in the SCTP packet*/void *private_data; /* pointer to data passed from one dissector to another *//* TODO: Use emem_strbuf_t instead */GString *layer_names; /* layers of each protocol */guint16 link_number;guint8 annex_a_used;guint16 profinet_type; /* the type of PROFINET packet (0: not a PROFINET packet) */void *profinet_conv; /* the PROFINET conversation data (NULL: not a PROFINET packet) */void *usb_conv_info;void *tcp_tree; /* proto_tree for the tcp layer */const char *dcerpc_procedure_name; /* Used by PIDL to store the name of the current dcerpc procedure */struct _sccp_msg_info_t* sccp_info;guint16 clnp_srcref; /* clnp/cotp source reference (can't use srcport, this would confuse tpkt) */guint16 clnp_dstref; /* clnp/cotp destination reference (can't use dstport, this would confuse tpkt) */guint16 zbee_cluster_id; /* ZigBee cluster ID, an application-specific message identifier that* happens to be included in the transport (APS) layer header.*/guint8 zbee_stack_vers; int link_dir; /* 3GPP messages are sometime different UP link(UL) or Downlink(DL)*/ } packet_info;因?yàn)槲业闹饕ぷ魇切薷膚ireshark存儲(chǔ)部分源代碼,還有必要從main開(kāi)始分析嗎?看到一層層的調(diào)用,要調(diào)暈了。。。。
博客寫(xiě)的有點(diǎn)亂了,總之,不知道如何開(kāi)始。。。。
總結(jié)
以上是生活随笔為你收集整理的winshark重要数据结构的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 如何调理宫寒呢
- 下一篇: wireshark源代码分析