1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
|
#include <hs/hs_common.h>
#include <hs/hs_runtime.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <MESA/MESA_prof_load.h>
#include <MESA/MESA_handle_logger.h>
#include <MESA/cJSON.h>
extern "C" {
#include <stellar/stellar.h>
#include <stellar/session.h>
#include <stellar/session_mq.h>
#include <stellar/session_exdata.h>
}
#include "pkt_seq_matcher.h"
#define UNUSED(x) (void)(x)
const char *CFG_FILE_PATH="stellar_plugin/pkt_seq_matcher.conf";
static int g_log_level=30;
void * g_logger_handle = NULL;
thread_local hs_scratch_t *hs_scratch = NULL;
thread_local char unicode_charactor[5] = {0};
// 函数用于将单个Unicode码点转换为UTF-8编码并存储到buffer中
static void encode_utf8(int codepoint, char *buffer)
{
int index = 0;
if (codepoint <= 0x7F) {
// 1字节UTF-8字符
buffer[(index)++] = codepoint;
} else if (codepoint <= 0x7FF) {
// 2字节UTF-8字符
buffer[(index)++] = 0xC0 | (codepoint >> 6);
buffer[(index)++] = 0x80 | (codepoint & 0x3F);
} else if (codepoint <= 0xFFFF) {
// 3字节UTF-8字符
buffer[(index)++] = 0xE0 | (codepoint >> 12);
buffer[(index)++] = 0x80 | ((codepoint >> 6) & 0x3F);
buffer[(index)++] = 0x80 | (codepoint & 0x3F);
} else if (codepoint <= 0x10FFFF) {
// 4字节UTF-8字符
buffer[(index)++] = 0xF0 | (codepoint >> 18);
buffer[(index)++] = 0x80 | ((codepoint >> 12) & 0x3F);
buffer[(index)++] = 0x80 | ((codepoint >> 6) & 0x3F);
buffer[(index)++] = 0x80 | (codepoint & 0x3F);
}
}
// 定义匹配事件的回调函数
static int eventHandler(unsigned int id, unsigned long long from, unsigned long long to, unsigned int flags, void *context) {
struct pkt_seq_matcher_ctx *ctx = (struct pkt_seq_matcher_ctx *)context;
ctx->match_flag = 1;
return 0; // 继续搜索
}
static int pkt_seq_matcher_hyperscan_init(struct pkt_seq_matcher_plugin_info *psm_plugin_info)
{
hs_error_t err;
hs_compile_error_t *compile_err;
const char *expression[6] = {"[\u00C9-\u03E8][\u099C-\u0B68]{3}[\u05B5-\u067C][\u0001-\u05B4]{0,3}[\u0001-\u0258][\u067D-\u080C][\u0001-\u05B4]",
"[\u00C9-\u03E8][\u099C-\u0B68]{3}[\u0001-\u05B4]{0,3}[\u0001-\u00C8][\u05B5-\u067C][\u0001-\u05B4]",
"[\u00C9-\u03E8][\u099C-\u0B68]{2}[\u067D-\u099C][\u0001-\u0258][\u067D-\u080C][\u0001-\u05B4]",
"[\u00C9-\u03E8][\u099C-\u0B68]{2}[\u067D-\u099C][\u0001-\u00C8][\u05B5-\u067C][\u0001-\u05B4]",
"[\u0259-\u03E8][\u05B5-\u067C][\u0001-\u05B4]",
"[\u0259-\u03E8][\u067D-\u080C][\u0001-\u05B4]"};
unsigned int flags[6] = {HS_FLAG_DOTALL | HS_FLAG_UTF8, HS_FLAG_DOTALL | HS_FLAG_UTF8, HS_FLAG_DOTALL | HS_FLAG_UTF8, HS_FLAG_DOTALL | HS_FLAG_UTF8, HS_FLAG_DOTALL | HS_FLAG_UTF8, HS_FLAG_DOTALL | HS_FLAG_UTF8};
unsigned int ids[6] = {0, 1, 2, 3, 4, 5};
hs_database_t *db = NULL;
err = hs_compile_multi(expression, flags, ids, 6, HS_MODE_STREAM, NULL, &db, &compile_err);
if (err != HS_SUCCESS) {
MESA_handle_runtime_log(g_logger_handle, RLOG_LV_FATAL, "PKT_SEQ_MATCHER", "compile failed: %d:%s, pattern:%s", compile_err->expression, compile_err->message, expression[compile_err->expression]);
hs_free_compile_error(compile_err);
return -1;
}
psm_plugin_info->hs_database = db;
MESA_handle_runtime_log(g_logger_handle, RLOG_LV_DEBUG, "PKT_SEQ_MATCHER", "hyperscan compile success");
return 0;
}
static void pkt_seq_matcher_exdata_free_cb(struct session *sess, int idx, void *ex_ptr, void *arg)
{
UNUSED(sess);
UNUSED(idx);
UNUSED(arg);
if (ex_ptr == NULL)
{
return;
}
struct pkt_seq_matcher_ctx *ctx = (struct pkt_seq_matcher_ctx *)ex_ptr;
hs_close_stream(ctx->hs_stream, hs_scratch, NULL, NULL);
free(ex_ptr);
}
int pkt_seq_matcher_entry(struct session *session, int events, const struct packet *pkt, void *cb_arg)
{
if (pkt == NULL)
{
return 0;
}
struct pkt_seq_matcher_plugin_info *psm_plugin_info = (struct pkt_seq_matcher_plugin_info *)cb_arg;
struct pkt_seq_matcher_ctx *ctx = (struct pkt_seq_matcher_ctx *)session_get_ex_data(session, psm_plugin_info->sess_ctx_exdata_idx);
size_t payload_len = 0;
int pkt_direction;
if (ctx == NULL)
{
ctx = (struct pkt_seq_matcher_ctx *)calloc(1, sizeof(struct pkt_seq_matcher_ctx));
session_set_ex_data(session, psm_plugin_info->sess_ctx_exdata_idx, ctx);
if (hs_scratch == NULL)
{
hs_error_t err = hs_alloc_scratch(psm_plugin_info->hs_database, &hs_scratch);
if (err != HS_SUCCESS) {
MESA_handle_runtime_log(g_logger_handle, RLOG_LV_FATAL, "PKT_SEQ_MATCHER", "alloc for scratch failed");
goto DETACH_SESSION;
}
}
hs_error_t err = hs_open_stream(psm_plugin_info->hs_database, 0, &ctx->hs_stream);
if (err != HS_SUCCESS) {
MESA_handle_runtime_log(g_logger_handle, RLOG_LV_FATAL, "PKT_SEQ_MATCHER", "%s: open stream failed", session_get0_readable_addr(session));
goto DETACH_SESSION;
}
}
session_get0_current_payload(session, &payload_len);
if (payload_len == 0)
{
return 0;
}
pkt_direction = packet_get_direction(pkt);
MESA_handle_runtime_log(g_logger_handle, RLOG_LV_DEBUG, "PKT_SEQ_MATCHER", "%s: payload_len: %d", pkt_direction == PACKET_DIRECTION_C2S ? "C2S" : "S2C", payload_len);
if (pkt_direction == PACKET_DIRECTION_S2C)
{
payload_len += 1460;
}
memset(unicode_charactor, 0, sizeof(unicode_charactor));
encode_utf8(payload_len, unicode_charactor);
if (hs_scan_stream(ctx->hs_stream, (const char *)unicode_charactor, strlen(unicode_charactor), 0, hs_scratch, eventHandler, ctx) != HS_SUCCESS)
{
MESA_handle_runtime_log(g_logger_handle, RLOG_LV_FATAL, "PKT_SEQ_MATCHER", "%s: scan failed, pkt_len: %d", session_get0_readable_addr(session), payload_len);
}
if (ctx->match_flag == 1)
{
MESA_handle_runtime_log(g_logger_handle, RLOG_LV_DEBUG, "PKT_SEQ_MATCHER", "%s: match success", session_get0_readable_addr(session));
goto DETACH_SESSION;
}
return 0;
DETACH_SESSION:
struct session_event *i_ev = session_get_intrinsic_event(session, psm_plugin_info->plugin_id);
session_event_assign(i_ev, psm_plugin_info->st, session, 0, pkt_seq_matcher_entry, psm_plugin_info);
return 0;
}
extern "C" void *pkt_seq_matcher_plugin_init(struct stellar *st)
{
char log_path[128]={0};
struct pkt_seq_matcher_plugin_info *psm_plugin_info = (struct pkt_seq_matcher_plugin_info *)calloc(1, sizeof(struct pkt_seq_matcher_plugin_info));
psm_plugin_info->st = st;
psm_plugin_info->sess_ctx_exdata_idx = stellar_session_get_ex_new_index(st, "PKT_SEQ_matcher_SESS_CTX", pkt_seq_matcher_exdata_free_cb, NULL);
MESA_load_profile_int_def(CFG_FILE_PATH, "PKT_SEQ_matcher","LOG_LEVEL", &g_log_level, 30);
MESA_load_profile_string_def(CFG_FILE_PATH, "PKT_SEQ_matcher","LOG_PATH", log_path, sizeof(log_path), "log/pkt_seq_matcher");
g_logger_handle = MESA_create_runtime_log_handle(log_path, g_log_level);
if(g_logger_handle == NULL)
{
printf("MESA_create_runtime_log object failed ...\n");
goto ERROR;
}
if (pkt_seq_matcher_hyperscan_init(psm_plugin_info) != 0)
{
goto ERROR;
}
psm_plugin_info->plugin_id = stellar_plugin_register(st, (SESS_EV_TCP|SESS_EV_UDP|SESS_EV_OPENING|SESS_EV_PACKET|SESS_EV_CLOSING), pkt_seq_matcher_entry, psm_plugin_info);
return psm_plugin_info;
ERROR:
if (psm_plugin_info != NULL)
{
free(psm_plugin_info);
}
return NULL;
}
extern "C" void pkt_seq_matcher_plugin_exit(void *plugin_ctx)
{
if (plugin_ctx == NULL)
{
return;
}
struct pkt_seq_matcher_plugin_info *psm_plugin_info = (struct pkt_seq_matcher_plugin_info *)plugin_ctx;
MESA_destroy_runtime_log_handle(g_logger_handle);
hs_free_database(psm_plugin_info->hs_database);
free(plugin_ctx);
return;
}
|