【智能路由器】系列文章连接
http://blog.csdn.net/u012819339/article/category/5803489


本篇博客讲述ndpi已经实现的QQ协议分析器的实现 以及 编写一个微信协议分析器的框架要点。
关于ndpi源码的叙述在上篇博客已有提及,点击这里(或者查看链接http://blog.csdn.net/u012819339/article/details/52443705)

ndpi协议分析器结构框架

每个协议分析器都必须定义一个独有的id,例如:

/*ndpi_protocol_ids.h*/
#define NDPI_PROTOCOL_QQ                    48

协议分析器格式

#include "ndpi_utils.h"
#ifdef NDPI_PROTOCOL_QQ
.....
#endif

协议分析器的初始化函数,初始化函数中调用ndpi_set_bitmask_protocol_detection来输入自己的注册信息,以及处理数据包的类型

void init_qq_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask)
{ndpi_set_bitmask_protocol_detection("QQ", ndpi_struct, detection_bitmask, *id,NDPI_PROTOCOL_QQ,ndpi_search_qq,NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD,SAVE_DETECTION_BITMASK_AS_UNKNOWN,ADD_TO_DETECTION_BITMASK);*id += 1;
}

一个回调函数,用来处理数据包,这个函数就是初始化中注册的函数,这个函数将细分情况,然后交给实际的分析函数,这里分别是ndpi_search_qq_udpndpi_search_qq_tcp。虽然也可以直接在这里分析处理,但这样会显得层次结构不清晰

void ndpi_search_qq(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
{struct ndpi_packet_struct *packet = &flow->packet;if (packet->udp != NULL && flow->detected_protocol_stack[0] != NDPI_PROTOCOL_QQ)ndpi_search_qq_udp(ndpi_struct, flow);if (packet->tcp != NULL && flow->detected_protocol_stack[0] != NDPI_PROTOCOL_QQ)ndpi_search_qq_tcp(ndpi_struct, flow);
}

协议分析器的框架就到此为止,然后将初始化函数添加到ndpi_main.c文件的ndpi_init_protocol_defaults函数中,像这样:

static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndpi_mod) {int i;ndpi_port_range ports_a[MAX_DEFAULT_PORTS], ports_b[MAX_DEFAULT_PORTS];u_int16_t no_master[2] = { NDPI_PROTOCOL_NO_MASTER_PROTO, NDPI_PROTOCOL_NO_MASTER_PROTO },custom_master[2];/* Reset all settings */memset(ndpi_mod->proto_defaults, 0, sizeof(ndpi_mod->proto_defaults));//......ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_QQ,no_master,no_master, "QQ",ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);//......
}

宏定义NDPI_PROTOCOL_LONG_STRINGNDPI_PROTOCOL_SHORT_STRING中添加协议名称字符串。
协议分析器的结构框架大概如此了

ndpi协议分析中QQ协议分析器的代码概要

根据packet是tcp还是udp将探测过程被分为两中情况:

void ndpi_search_qq(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
{struct ndpi_packet_struct *packet = &flow->packet;if (packet->udp != NULL && flow->detected_protocol_stack[0] != NDPI_PROTOCOL_QQ)ndpi_search_qq_udp(ndpi_struct, flow);if (packet->tcp != NULL && flow->detected_protocol_stack[0] != NDPI_PROTOCOL_QQ)ndpi_search_qq_tcp(ndpi_struct, flow);
}

看一下qq的udp报文是怎么探测的,在下面这个函数中


static void ndpi_search_qq_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
{struct ndpi_packet_struct *packet = &flow->packet;static const u_int16_t p8000_patt_02[13] =    // maybe version numbers{ 0x1549, 0x1801, 0x180d, 0x0961, 0x01501, 0x0e35, 0x113f, 0x0b37, 0x1131, 0x163a, 0x1e0d, 0x3619,};u_int16_t no_of_patterns = 12, index = 0;NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "search qq udp.\n");if (flow->qq_stage <= 3) {if ((packet->payload_packet_len == 27 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x0300&& packet->payload[2] == 0x01)|| (packet->payload_packet_len == 84 && ((ntohs(get_u_int16_t(packet->payload, 0)) == 0x000e&& packet->payload[2] == 0x35)|| (ntohs(get_u_int16_t(packet->payload, 0)) == 0x0015&& packet->payload[2] == 0x01)|| (ntohs(get_u_int16_t(packet->payload, 0)) == 0x000b&& packet->payload[2] == 0x37)|| (ntohs(get_u_int16_t(packet->payload, 0)) == 0x0015&& packet->payload[2] == 0x49)))|| (packet->payload_packet_len > 10&& ((get_u_int16_t(packet->payload, 0) == htons(0x000b) && packet->payload[2] == 0x37)|| (get_u_int32_t(packet->payload, 0) == htonl(0x04163a00)&& packet->payload[packet->payload_packet_len - 1] == 0x03&& packet->payload[4] == packet->payload_packet_len)))) {/*if (flow->qq_stage == 3 && flow->detected_protocol == NDPI_PROTOCOL_QQ) {if (flow->packet_direction_counter[0] > 0 && flow->packet_direction_counter[1] > 0) {flow->protocol_subtype = NDPI_PROTOCOL_QQ_SUBTYPE_AUDIO;return;} else if (flow->packet_counter < 10) {return;}} */flow->qq_stage++;if (flow->qq_stage == 3) {NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG,"found qq udp pattern 030001 or 000e35 four times.\n");ndpi_int_qq_add_connection(ndpi_struct, flow);return;}return;}if (packet->payload_packet_len > 2 && (packet->payload[0] == 0x02 || packet->payload[0] == 0x04)) {u_int16_t pat = ntohs(get_u_int16_t(packet->payload, 1));for (index = 0; index < no_of_patterns; index++) {if (pat == p8000_patt_02[index] && packet->payload[packet->payload_packet_len - 1] == 0x03) {flow->qq_stage++;// maybe we can test here packet->payload[4] == packet->payload_packet_lenif (flow->qq_stage == 3) {NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG,"found qq udp pattern 02 ... 03 four times.\n");/*if (packet->payload[0] == 0x04) {ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);return;} */ndpi_int_qq_add_connection(ndpi_struct, flow);return;}return;}}}if (packet->payload_packet_len == 84 && (packet->payload[0] == 0 || packet->payload[0] == 0x03)) {u_int16_t pat = ntohs(get_u_int16_t(packet->payload, 1));for (index = 0; index < no_of_patterns; index++) {if (pat == p8000_patt_02[index]) {flow->qq_stage++;/*if (flow->qq_stage == 3 && flow->packet_direction_counter[0] > 0 &&flow->packet_direction_counter[1] > 0) {NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq udp pattern four times.\n");ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);return;} else */ if (flow->qq_stage == 3) {NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq udp pattern four times.\n");ndpi_int_qq_add_connection(ndpi_struct, flow);return;}return;}}}if (packet->payload_packet_len > 2 && packet->payload[0] == 0x04&& ((ntohs(get_u_int16_t(packet->payload, 1)) == 0x1549|| ntohs(get_u_int16_t(packet->payload, 1)) == 0x1801 || ntohs(get_u_int16_t(packet->payload, 1)) == 0x0961)||(packet->payload_packet_len > 16&& (ntohs(get_u_int16_t(packet->payload, 1)) == 0x180d || ntohs(get_u_int16_t(packet->payload, 1)) == 0x096d)&& ntohl(get_u_int32_t(packet->payload, 12)) == 0x28000000&& ntohs(get_u_int16_t(packet->payload, 3)) == packet->payload_packet_len))&& packet->payload[packet->payload_packet_len - 1] == 0x03) {flow->qq_stage++;if (flow->qq_stage == 3) {NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG,"found qq udp pattern 04 1159 ... 03 four times.\n");ndpi_int_qq_add_connection(ndpi_struct, flow);return;}return;}if (packet->payload_packet_len > 2 && (packet->payload[0] == 0x06 || packet->payload[0] == 0x02)&& ntohs(get_u_int16_t(packet->payload, 1)) == 0x0100&& (packet->payload[packet->payload_packet_len - 1] == 0x00|| packet->payload[packet->payload_packet_len - 1] == 0x03)) {flow->qq_stage++;if (flow->qq_stage == 3) {NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG,"found qq udp pattern 02/06 0100 ... 03/00 four times.\n");ndpi_int_qq_add_connection(ndpi_struct, flow);return;}return;}if (packet->payload_packet_len > 2 && (packet->payload[0] == 0x02)&& ntohs(get_u_int16_t(packet->payload, 1)) == 0x1131 && packet->payload[packet->payload_packet_len - 1] == 0x03) {flow->qq_stage++;if (flow->qq_stage == 3) {NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG,"found qq udp pattern 02 1131 ... 03 four times.\n");ndpi_int_qq_add_connection(ndpi_struct, flow);return;}return;}if (packet->payload_packet_len > 5 && get_u_int16_t(packet->payload, 0) == htons(0x0203) &&ntohs(get_u_int16_t(packet->payload, 2)) == packet->payload_packet_len &&get_u_int16_t(packet->payload, 4) == htons(0x0b0b)) {flow->qq_stage++;if (flow->qq_stage == 3) {NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG,"found qq udp pattern 0203[packet_length_0b0b] three times.\n");ndpi_int_qq_add_connection(ndpi_struct, flow);return;}return;}if (packet->udp->dest == htons(9000) || packet->udp->source == htons(9000)) {if (packet->payload_packet_len > 3&& ntohs(get_u_int16_t(packet->payload, 0)) == 0x0202&& ntohs(get_u_int16_t(packet->payload, 2)) == packet->payload_packet_len) {flow->qq_stage++;if (flow->qq_stage == 3) {NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG,"found qq udp pattern 02 02 <length> four times.\n");ndpi_int_qq_add_connection(ndpi_struct, flow);return;}return;}}}if (ndpi_is_valid_qq_packet(packet)) {flow->qq_stage++;if (flow->qq_stage == 3) {NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq over udp.\n");ndpi_int_qq_add_connection(ndpi_struct, flow);return;}NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq packet stage %d\n", flow->qq_stage);return;}if (ndpi_is_valid_qq_ft_packet(packet)) {flow->qq_stage++;if (flow->qq_stage == 3) {NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq ft over udp.\n");ndpi_int_qq_add_connection(ndpi_struct, flow);return;}return;}if (flow->qq_stage && flow->packet_counter <= 5) {return;}NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "QQ excluded\n");NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_QQ);
}

该函数有点长,不过基本都是属于探测OICQ协议的报头,oicq协议是qq用于即时通信的协议,数据流经8000端口,具体oicq协议头的解释可参看arvik的另一篇博客http://blog.csdn.net/u012819339/article/details/50374252

得到payload头指针后起始可以直接强制指针类型转换成 oicqhdr *,就比较方便啦

typedef struct _oicqhdr {uint8_t flag;uint16_t ver;uint16_t command;uint16_t sequence;uint32_t qq;
} __attribute__((packed)) oicqhdr;

tcp检测就不叙述了,总之都是先抓包分析QQ报文头的结构特征,然后拿到协议分析器中做匹配。

ndpi协议分析中编写一个微信协议分析器的方法指导

协议分析器框架见上文所述,可以参照QQ协议分析器依葫芦画瓢,
这里主要是弄清微信协议的格式,这需要自己抓包分析,arvik已经做好了一部分微信抓包分析的过程,见我的博客微信数据包(链接地址http://blog.csdn.net/u012819339/article/details/52588288),微信客户端有很多模块,比如发红包,漂流瓶,摇一摇,传图片,发语音,发短视频等等,每个模块都可能会有一种协议格式,arvik并没有完全对这些模块进行分析,需要开发者自行抓包。


好了,本文到此结束,作者arvik。
【智能路由器】系列文章连接
http://blog.csdn.net/u012819339/article/category/5803489

【智能路由器】ndpi深度报文分析之协议分析器相关推荐

  1. 【智能路由器】ndpi深度报文分析源码框架

    [智能路由器]系列文章连接 http://blog.csdn.net/u012819339/article/category/5803489 某些需求可能会要求路由能精确的分析出流经路由的流量是属于什 ...

  2. 【智能路由器】打赏连wifi

    [智能路由器]系列文章连接 http://blog.csdn.net/u012819339/article/category/5803489 打赏连wifi是最近路由上的一个新功能,每个需要通过路由上 ...

  3. DPI(Deep packet inspection,深度报文解析)

    DPI(Deep packet inspection,深度报文解析) 正好,有这么一个基于opendpi框架的深度报文分析的工具--ndpi ndpi是在opendpi的基础上编写而来的协议分析工具. ...

  4. 智能路由器开发之OpenWrt简介

    智能路由器开发之OpenWrt简介 1. 引言 1.1 智能路由器的重要性和应用场景 智能路由器作为网络通信的核心设备,具有重要的地位和广泛的应用场景.传统的路由器主要提供基本的网络连接功能,但随着智 ...

  5. 【智能路由器】离线缓存投毒实现分析

    [智能路由器]系列文章连接 http://blog.csdn.net/u012819339/article/category/5803489 在路由器上实现广告植入已不是什么新鲜技术,绝大部分免费公共 ...

  6. Virtual-Network--—DHCP协议学习以及对应报文分析

    文章目录 Virtual-Network---DHCP协议学习以及对应报文分析 转载 1. DHCP 简介 1.1 DHCP 作用 1.2 DHCP 工作机制 2. DHCP 交互流程 2.1 正常交 ...

  7. 智能路由器OpenWrt 开发环境 及 编译分析(一)

    OpenWrt 开发环境及编译分析 OpenWrt的版本:Chaos Calmer 15.05 软件源:软件源就是一个应用程序安装库,很多很多的应用软件都在这个库里面.只要设定好软件源,就能很方便的安 ...

  8. MQTT协议-报文分析及网络客户端报文测试(MQTT报文连接阿里云上传数据+订阅数据)

    文章目录 一.本文章所涉及到的内容 二.感性认识MQTT协议 三.准备信息 (一)工具获取 (二)获取信息 1.获取三元组信息 2.获取发布topic和订阅topic 3.客户端ID,用户名,哈希加密 ...

  9. 头歌 DNS协议分析 第4关 NS 类型的 DNS 解析报文分析

    任务描述 相关知识 如何捕获 NS 类型的 DNS 报文 解析 DNS 请求报文 传输层协议使用 TCP 还是 UDP ? 解析 DNS 应答报文 操作要求 测试说明 任务描述 本关任务:分析 NS ...

最新文章

  1. 别在 Java 代码里乱打日志了,这才是正确的日志打印姿势!
  2. pdf转换为word问题
  3. 跨域解决方案之CORS
  4. linux设备驱动学习(三)——并发控制
  5. mat工具MemoryAnalyzer进行分析java内存溢出hprof文件
  6. 【已解决】Error attaching to process: sun.jvm.hotspot.runtime.VMVersionMismatchException: Supported versi
  7. JSP的生命周期研究
  8. Expression Template(表达式模板,ET)
  9. 小米12 mini曝光:骁龙898加持
  10. 烂泥:LVM学习之LVM基础
  11. 谷粒商城 Day04 sku与spu接口
  12. java监控屏幕_Java实现简单屏幕监控
  13. 新内容创业时代,微博的造“星”哲学
  14. 加权移动平均法 java_加权平均和移动平均
  15. SharePoint Designer定制MOSS/WSS表单页面
  16. day01 错误1
  17. HTML5——meta标签总结
  18. 智商情商哪个重要_智商和情商哪个更重要 一辩辩词
  19. MSP430F149;一、TIMEA
  20. 英语语法汇总(4.数量词)

热门文章

  1. 懒人听书java_基础02 Java 跨平台原理
  2. 联通雁飞格物IOT接入烟感和扬尘
  3. 中国用户使用代理软件的分析
  4. QMT量化交易软件使用攻略(四)-策略回测
  5. Derivation of the mathematical formula of gradient descent
  6. (1)前言——(15)勘误表(Errata)
  7. 这种思维跟客户,一跟一个准儿
  8. 归并排序的递归与非递归方式(python)
  9. 关于输入法的工作原理及编程
  10. 使用 Go 从零开发并发布一个 Kubectl 插件