searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

Hyperscan使用示例

2023-08-31 03:39:38
371
0

Hyperscan是Intel的高性能正则表达式引擎,能支持几十万规则的同步匹配。自推出起即被广泛应用于字符串匹配。本文以QQ为例,介绍Hyperscan通过匹配完成识别的一个具体使用示范。

QQ使用TCP和UDP两种协议,使用不同的协议时净载荷的结构也略有不同。本文以使用UDP为例,对应抓包示例如下图所示。使用UDP协议时,数据净载荷部分以0x02开始、0x03结尾,本地端口通常从8000端口开始,多登录一个QQ终端使用端口则相应增加如8001、8002等。

Hyperscan的工作流程分为编译期和运行期。编译期将正则表达式作为输入,生成对应的数据库。该数据库可以被序列化后进行存储,供运行期提取使用;运行期则利用编译生成的数据库调用匹配引擎对输入进行模式匹配,可通过回调函数来自定义匹配发生后采取的行为。

Hyperscan分为块模式(block)和流模式(stream)两种模式。块模式对一段现成的完整数据进行匹配,匹配结束返回结果;流模式则是针对网络场景下跨报文匹配设计的特殊匹配模式。本示例中QQ的特征在一个完整的数据包中,采用块模式匹配。

首先,我们进入编译阶段。先定义编译需要的QQ相关的字段

qq_expr[]="^\x02.+\x03$";//QQ的对应正则表达式文件

qq_flag=HS_FLAG_DOTALL;

qq_id=1;//设置QQ对应的ID为1

然后调用编译函数完成编译

hs_compile_multi(qq_expr, qq_flag, qq_id, 1, HS_MODE_BLOCK, NULL, &qq_database, &hs_compile_err);

qq_database是编译生成的数据库。编译好后,再分配一段运行期需要的内存scratch:

hs_alloc_scratch(qq_database, qq_scratch);

然后,针对网络数据包,解析数据包头后,拿到净载荷payload及对应长度length。再利用database和scratch通过hs_scan函数运行完成匹配。

我们这里简单定义一个回调函数,命中后打印一条信息。

static int match_handler(unsigned int id, unsigned long long from,

                        unsigned long long to, unsigned int flags, void *ctx)

{

    printf("Hey,It's QQ!");

    return 0;

}

hs_scan(qq_database, payload, length, 0,qq_stratch, match_handler,NULL);

如此,在有QQ的UDP数据包时,就能匹配命中并进行相应打印。

使用结束时,调用hs_free_database(qq_database)以及hs_free_scratch(qq_scratch)完成对使用资源的释放。

以上就是一次简单的利用Hyperscan实现字符串匹配的完整过程,是一次针对QQ的简单DPI实现。

0条评论
0 / 1000
M****n
2文章数
0粉丝数
M****n
2 文章 | 0 粉丝
M****n
2文章数
0粉丝数
M****n
2 文章 | 0 粉丝
原创

Hyperscan使用示例

2023-08-31 03:39:38
371
0

Hyperscan是Intel的高性能正则表达式引擎,能支持几十万规则的同步匹配。自推出起即被广泛应用于字符串匹配。本文以QQ为例,介绍Hyperscan通过匹配完成识别的一个具体使用示范。

QQ使用TCP和UDP两种协议,使用不同的协议时净载荷的结构也略有不同。本文以使用UDP为例,对应抓包示例如下图所示。使用UDP协议时,数据净载荷部分以0x02开始、0x03结尾,本地端口通常从8000端口开始,多登录一个QQ终端使用端口则相应增加如8001、8002等。

Hyperscan的工作流程分为编译期和运行期。编译期将正则表达式作为输入,生成对应的数据库。该数据库可以被序列化后进行存储,供运行期提取使用;运行期则利用编译生成的数据库调用匹配引擎对输入进行模式匹配,可通过回调函数来自定义匹配发生后采取的行为。

Hyperscan分为块模式(block)和流模式(stream)两种模式。块模式对一段现成的完整数据进行匹配,匹配结束返回结果;流模式则是针对网络场景下跨报文匹配设计的特殊匹配模式。本示例中QQ的特征在一个完整的数据包中,采用块模式匹配。

首先,我们进入编译阶段。先定义编译需要的QQ相关的字段

qq_expr[]="^\x02.+\x03$";//QQ的对应正则表达式文件

qq_flag=HS_FLAG_DOTALL;

qq_id=1;//设置QQ对应的ID为1

然后调用编译函数完成编译

hs_compile_multi(qq_expr, qq_flag, qq_id, 1, HS_MODE_BLOCK, NULL, &qq_database, &hs_compile_err);

qq_database是编译生成的数据库。编译好后,再分配一段运行期需要的内存scratch:

hs_alloc_scratch(qq_database, qq_scratch);

然后,针对网络数据包,解析数据包头后,拿到净载荷payload及对应长度length。再利用database和scratch通过hs_scan函数运行完成匹配。

我们这里简单定义一个回调函数,命中后打印一条信息。

static int match_handler(unsigned int id, unsigned long long from,

                        unsigned long long to, unsigned int flags, void *ctx)

{

    printf("Hey,It's QQ!");

    return 0;

}

hs_scan(qq_database, payload, length, 0,qq_stratch, match_handler,NULL);

如此,在有QQ的UDP数据包时,就能匹配命中并进行相应打印。

使用结束时,调用hs_free_database(qq_database)以及hs_free_scratch(qq_scratch)完成对使用资源的释放。

以上就是一次简单的利用Hyperscan实现字符串匹配的完整过程,是一次针对QQ的简单DPI实现。

文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
0
0