• 【wireshark】协议解析


    1. 普通解析

    Wireshark启动时,所有解析器进行初始化和注册。要注册的信息包括协议名称、各个字段的信息、过滤用的关键字、要关联的下层协议与端口(handoff)等。在解析过程,每个解析器负责解析自己的协议部分, 然后把上层封装数据传递给后续协议解析器,这样就构成一个完整的协议解析链条。

    解析链条的最上端是Frame解析器,它负责解析pcap帧头。后续该调用哪个解析器,是通过上层协议注册handoff信息时写在当前协议的hash表来查找的。

    例如,考虑ipv4解析器有一个hash表,里面存储的信息形如下表。当它解析完ipv4首部后,就可以根据得到的协议号字段,比如6,那么它就能从此hash表中找到后续解析器tcp。

    协议号 解析器指针
    6 *tcp
    17 *udp
    ……

    Wireshark中实际的解析表有3种,分别是字符串表,整数表和启发式解析表。如下图所示:

    下面以ip协议为例,说明一下它的注册过程。

    相关的重要数据结构与全局变量如下。

    proto.c

    /* Name hashtables for fast detection of duplicate names */
    static GHashTable* proto_names        = NULL;
    static GHashTable* proto_short_names  = NULL;
    static GHashTable* proto_filter_names = NULL;
    
    /** Register a new protocol.
     @param name the full name of the new protocol
     @param short_name abbreviated name of the new protocol
     @param filter_name protocol name used for a display filter string
     @return the new protocol handle */
    int
    proto_register_protocol(const char *name, const char *short_name, const char *filter_name);

    三个全局的哈希表分别用于保存协议名称、协议缩略名和用于过滤器的协议名。

    packet.c:

    struct dissector_table {
        GHashTable    *hash_table;
        GSList    *dissector_handles;
        const char    *ui_name;
        ftenum_t    type;
        int        base;
    };
    
    static GHashTable *dissector_tables = NULL;
    
    /*
     * List of registered dissectors.
     */
    static GHashTable *registered_dissectors = NULL;
    static GHashTable *heur_dissector_lists = NULL;
    
    /* Register a dissector by name. */
    dissector_handle_t
    register_dissector(const char *name, dissector_t dissector, const int proto);
    
    /** A protocol uses this function to register a heuristic sub-dissector list.
     *  Call this in the parent dissectors proto_register function.
     *
     * @param name the name of this protocol
     * @param list the list of heuristic sub-dissectors to be registered
     */
    void register_heur_dissector_list(const char *name,
        heur_dissector_list_t *list);
    
    /* a protocol uses the function to register a sub-dissector table */
    dissector_table_t register_dissector_table(const char *name, const char *ui_name, const ftenum_t type, const int base);

    dissector_tables可以说是“哈希表的哈希表”,它以解析表名为键(如“ip.proto”),以dissector_table结构指针为值。在dissector_table中的哈希表以无符号数的指针为键(如协议号,为指针是glib hash表API的参数要求),以解析器handle为值;heur_dissector_lists是启发式解析相关的东西,这个问题留待以后研究;registered_dissectors是解析器哈希表,它以解析器名为键(如”ip”),以解析器句柄为值。

    packet.h:

    typedef struct dissector_table *dissector_table_t;

    packet-ip.c:

    static dissector_table_t ip_dissector_table;

    proto_register_ip函数中:

     proto_ip = proto_register_protocol("Internet Protocol Version 4", "IPv4", "ip");
    ...
    /* subdissector code */
      ip_dissector_table = register_dissector_table("ip.proto", "IP protocol", FT_UINT8, BASE_DEC);
      register_heur_dissector_list("ip", &heur_subdissector_list);
    ...
      register_dissector("ip", dissect_ip, proto_ip);
      register_init_routine(ip_defragment_init);
      ip_tap = register_tap("ip");

    register_dissector_table这个函数在packet.c中,在此函数内,创建了名为“ip.proto”的哈希表。解析ip协议后,会查询这个表,找出下一个解析器,并将后续数据的解析移交给它。

    packet-ip.c,dissect_ip函数内:

    dissector_try_uint_new(ip_dissector_table, nxt, next_tvb, pinfo,
                                     parent_tree, TRUE, iph)

    packet.c:

    /* Look for a given value in a given uint dissector table and, if found, call the dissector with the arguments supplied, and return TRUE, otherwise return FALSE. */
    gboolean
    dissector_try_uint_new(dissector_table_t sub_dissectors, const guint32 uint_val, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const gboolean add_proto_name, void *data)

    在dissector_try_uint_new函数中,会找到协议号对应的解析器句柄,并使用它解析其余数据。

    2. 启发式(heuristic)解析

    //TODO

    3. 参考

    Wireshark开发指南第6章"How wireshark works"

  • 相关阅读:
    Git -- 分支管理简介
    Git -- 从远程库克隆
    Git -- 添加远程仓库
    C# sha256 加密算法
    如何将IOS版本的更新下载文件指向到自己的服务器
    如何让windows服务器IIS支持.apk/.ipa文件下载
    vistual studio 去除 git 源代码 绑定
    Redis 环境搭建与使用(C#)
    c#图片添加水印
    C#使用WSDL服务总结
  • 原文地址:https://www.cnblogs.com/zzqcn/p/4823243.html
Copyright © 2020-2023  润新知