搞网络开发的时候,涉及到很多私有协议。方便是方便,不过抓包分析问题就麻烦了,wireshark是不可能会为我们自己的网络协议开发分析工具的,唯有自己开发协议分析插件。在私有协议方面,google protobuf是一个类似与IDL的语言,用于定义消息接口,并且支持很多语言,原生支持C++、Java和python,而且还有很多第三方的支持,基本上支持C、C#、object-c,AS3,PHP等.目前protobuf的解析并不是wireshark内置支持的,不排除以后的版本会支持。当前网络上有一个工程可以支持protobuf的解析(protobuf-wireshark),但是该插件原生支持的只有linux版本,而且还只支持UDP解析。经本人改造,已经可以支持windows,并且同时支持TCP和UDP解析。TCP时,需要在protobuf之上加上一个4字节的数据长度,用于支持后续的protobuf消息的大小。
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
消息长度 protobuf二进制消息内容
消息长度的值只包含protobuf消息的大小,不包含自己4个字节的长度。例如protobuf长度为12字节时, 消息长度里面的值,应该是 00 00 00 0c,总的数据长度为16个字节.(如果无法解析数据长度,调换一下网络字节序)
另外对protobuf消息的定义也有一定的限制,必须有一个顶层的消息,例如Message1 和Message2如果是并列的消息,需要有一个Message来包含Message1和Message2.
【配置】
protobuf的配置文件放在C:\Program Files\Wireshark\protobuf目录下面,C:\Program Files\Wireshark\为wireshark在电脑上的安装目录。protobuf文件夹默认是没有的,自己创建。
把附件 *.proto;*.conf放在protobuf目录下面,把dll放在plugins\1.8.6目录下面。
protobuf-wireshark 插件下载, 测试包下载
插件代码:(代码基于google 上面的protobuf-wireshark 修改)
packet-protobuf.h
- #ifdef HAVE_CONFIG_H
- # include "config.h"
- #endif
- #include <gmodule.h>
- #include <epan/packet.h>
- #include <epan/prefs.h>
- #include <epan/emem.h>
- #include <epan/dissectors/packet-tcp.h>
- #include <epan/filesystem.h>
- #include <errno.h>
- #include <string.h>
- /* TCP数据包的固定头大小*/
- #define FRAME_HEADER_LEN 4
- void proto_register_protobuf();
- void proto_reg_handoff_protobuf();
- static void dissect_protobuf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
- static void dissect_protobuf_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
- /* Define version if we are not building ethereal statically */
- #ifndef ENABLE_STATIC
- G_MODULE_EXPORT const gchar version[] = "0.0";
- #endif
- static int proto_protobuf = -1;
- static dissector_handle_t protobuf_handle;
- // Protocol field variables - START
- static int hf_protobuf = -1;
- // Protocol field variables - END
- int wireshark_pb_process_protobuf(void *tree_root, int srcport, int dstport, int item_id, void *tvb, void *buf, int buf_size);
- void wireshark_pb_process_protobuf_register_proto( int proto, const char* dirname );
- void wireshark_pb_process_protobuf_register_ports();
- void wireshark_pb_process_protobuf_register_subtree( int proto, const char* name,
- int *handle, int ** tree_handle );
- void wireshark_pb_process_protobuf_register_field( int proto, int type,
- const char* name, const char * fullName,
- int *handle );
- /* Register plugin - START */
- #ifndef ENABLE_STATIC
- G_MODULE_EXPORT void
- plugin_register(void) {
- /* register the new protocol, protocol fields, and subtrees */
- if (proto_protobuf == -1) { /* execute protocol initialization only once */
- proto_register_protobuf();
- }
- }
- G_MODULE_EXPORT void
- plugin_reg_handoff(void){
- proto_reg_handoff_protobuf();
- }
- #endif
- void proto_register_protobuf(void) {
- module_t *protobuf_module;
- char* dirname;
- if (proto_protobuf == -1) {
- proto_protobuf = proto_register_protocol (
- "protobuf ",/* name */
- "protobuf",/* short name */
- "protobuf"/* abbrev */
- );
- }
- protobuf_module= prefs_register_protocol(proto_protobuf, proto_reg_handoff_protobuf);
- /*char**/ dirname = get_persconffile_path("protobuf", FALSE, FALSE);
- if( test_for_directory( dirname ) != EISDIR )
- {
- /* Although dir isn't a directory it may still use memory */
- g_free( dirname );
- dirname = get_datafile_path("protobuf");
- if( test_for_directory( dirname ) != EISDIR )
- {
- g_free( dirname );
- dirname = NULL;
- }
- }
- wireshark_pb_process_protobuf_register_proto( proto_protobuf, dirname );
- }
- void proto_reg_handoff_protobuf (void) {
- static int Initialized=FALSE;
- unsigned int i = 0;
- if (!Initialized) {
- protobuf_handle = create_dissector_handle(dissect_protobuf, proto_protobuf);
- wireshark_pb_process_protobuf_register_ports();
- }
- }
- /* Register plugin - END */
- /* 解析一个TCP数据包,wireshark会自动做分包和合并处理,此数据是一个完成的数据包,包含包头的内容*/
- static void dissect_protobuf_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
- {
- /* TODO: implement your dissecting code */\
- if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "protobuf-tcp");
- }
-
- /* Clear out stuff in the info column */
- if(check_col(pinfo->cinfo,COL_INFO)){
- col_clear(pinfo->cinfo,COL_INFO);
- }
-
-
- if (tree) { /* we are being asked for details */
-
- /* Always make sure that offset is LESS than maxOffset */
- gint data_len = tvb_get_ntohl(tvb, 0);
- proto_item * ti = NULL;
- tvbuff_t * next_tvb = tvb_new_subset_remaining (tvb,4);
- gint maxOffset = tvb_length(next_tvb);
- ti = proto_tree_add_item(tree,proto_protobuf,tvb,0,4,ENC_NA);
- proto_item_append_text(ti, ", Length %d",data_len);
- wireshark_pb_process_protobuf((void *) tree, pinfo->srcport, pinfo->destport, hf_protobuf,
- (void *)next_tvb, (void *)tvb_get_ptr(next_tvb,0,data_len), data_len);
- }
- }
- /* TCP数据包的总长度,包含包头长度 */
- static guint get_protobuf_message_len(packet_info *pinfo, tvbuff_t *tvb, int offset)
- {
- /* TODO: change this to your needs */
- return (guint)tvb_
复制代码 |