【智能路由器】ndpi深度报文分析之协议分析器
【智能路由器】系列文章连接
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_udp
和ndpi_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_STRING
和NDPI_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深度报文分析之协议分析器相关推荐
- 【智能路由器】ndpi深度报文分析源码框架
[智能路由器]系列文章连接 http://blog.csdn.net/u012819339/article/category/5803489 某些需求可能会要求路由能精确的分析出流经路由的流量是属于什 ...
- 【智能路由器】打赏连wifi
[智能路由器]系列文章连接 http://blog.csdn.net/u012819339/article/category/5803489 打赏连wifi是最近路由上的一个新功能,每个需要通过路由上 ...
- DPI(Deep packet inspection,深度报文解析)
DPI(Deep packet inspection,深度报文解析) 正好,有这么一个基于opendpi框架的深度报文分析的工具--ndpi ndpi是在opendpi的基础上编写而来的协议分析工具. ...
- 智能路由器开发之OpenWrt简介
智能路由器开发之OpenWrt简介 1. 引言 1.1 智能路由器的重要性和应用场景 智能路由器作为网络通信的核心设备,具有重要的地位和广泛的应用场景.传统的路由器主要提供基本的网络连接功能,但随着智 ...
- 【智能路由器】离线缓存投毒实现分析
[智能路由器]系列文章连接 http://blog.csdn.net/u012819339/article/category/5803489 在路由器上实现广告植入已不是什么新鲜技术,绝大部分免费公共 ...
- Virtual-Network--—DHCP协议学习以及对应报文分析
文章目录 Virtual-Network---DHCP协议学习以及对应报文分析 转载 1. DHCP 简介 1.1 DHCP 作用 1.2 DHCP 工作机制 2. DHCP 交互流程 2.1 正常交 ...
- 智能路由器OpenWrt 开发环境 及 编译分析(一)
OpenWrt 开发环境及编译分析 OpenWrt的版本:Chaos Calmer 15.05 软件源:软件源就是一个应用程序安装库,很多很多的应用软件都在这个库里面.只要设定好软件源,就能很方便的安 ...
- MQTT协议-报文分析及网络客户端报文测试(MQTT报文连接阿里云上传数据+订阅数据)
文章目录 一.本文章所涉及到的内容 二.感性认识MQTT协议 三.准备信息 (一)工具获取 (二)获取信息 1.获取三元组信息 2.获取发布topic和订阅topic 3.客户端ID,用户名,哈希加密 ...
- 头歌 DNS协议分析 第4关 NS 类型的 DNS 解析报文分析
任务描述 相关知识 如何捕获 NS 类型的 DNS 报文 解析 DNS 请求报文 传输层协议使用 TCP 还是 UDP ? 解析 DNS 应答报文 操作要求 测试说明 任务描述 本关任务:分析 NS ...
最新文章
- 别在 Java 代码里乱打日志了,这才是正确的日志打印姿势!
- pdf转换为word问题
- 跨域解决方案之CORS
- linux设备驱动学习(三)——并发控制
- mat工具MemoryAnalyzer进行分析java内存溢出hprof文件
- 【已解决】Error attaching to process: sun.jvm.hotspot.runtime.VMVersionMismatchException: Supported versi
- JSP的生命周期研究
- Expression Template(表达式模板,ET)
- 小米12 mini曝光:骁龙898加持
- 烂泥:LVM学习之LVM基础
- 谷粒商城 Day04 sku与spu接口
- java监控屏幕_Java实现简单屏幕监控
- 新内容创业时代,微博的造“星”哲学
- 加权移动平均法 java_加权平均和移动平均
- SharePoint Designer定制MOSS/WSS表单页面
- day01 错误1
- HTML5——meta标签总结
- 智商情商哪个重要_智商和情商哪个更重要 一辩辩词
- MSP430F149;一、TIMEA
- 英语语法汇总(4.数量词)