1 /*
2  * C-Code Rule Example
3  */
4 
5 #ifdef HAVE_CONFIG_H
6 #include "config.h"
7 #endif
8 
9 #include "sf_snort_plugin_api.h"
10 #include "detection_lib_meta.h"
11 
12 /* Forward Declaration */
13 int sid2519Eval(void *p);
14 
15 /*
16 alert tcp $EXTERNAL_NET any -> $SMTP_SERVERS 465 (msg:"SMTP Client_Hello overflow attempt";
17 flow:to_server,established; content:"|01|"; depth:1; offset:2; byte_test:2,>,0,6;
18 byte_test:2,!,0,8; byte_test:2,!,16,8; byte_test:2,>,20,10; content:"|8F|"; depth:1;
19 offset:11; byte_test:2,>,32768,0,relative; reference:bugtraq,10116; reference:cve,2003-0719;
20 reference:url,www.microsoft.com/technet/security/bulletin/MS04-011.mspx;
21 classtype:attempted-admin; sid:2519; rev:9;)
22  *
23 */
24 
25 /* The GUI will run snort with a special flag to extract this information,
26  * and generate a skeleton rule file with
27  *   SRC IP/PORT info,
28  *   DST IP/PORT info,
29  *   Message
30  *   SID
31  *   GID
32  *   REV
33  *   References
34  *
35  * This skeleton rule file will be read as a normal rules file (just no
36  * rule matching options specified.  When the shared library is loaded,
37  * it will access the loaded rule info (by SID/GID hash) and update the
38  * rest of the rule structure for processing (ie, handle any flowbits
39  * checks, content & pcre premung'ing, & fast pattern registration.
40  *
41  * A check will be made for the rule revision.  Rule data will different
42  * revision info, or non-existant SID/GIDs will cause a snort startup error.
43  *
44  */
45 static RuleReference ref1 =
46 {
47     "bugtraq",                  /* System Name */
48     "10116"                      /* ID */
49 };
50 
51 static RuleReference ref2 =
52 {
53     "cve",                      /* System Name */
54     "2003-0719"                 /* ID */
55 };
56 
57 static RuleReference ref3 =
58 {
59     "url",                      /* System Name */
60     "www.microsoft.com/technet/security/bulletin/MS04-011.mspx"
61 };
62 
63 static RuleReference *refs[] =
64 {
65     &ref1,
66     &ref2,
67     &ref3,
68     NULL
69 };
70 
71 
72 static FlowFlags flowflags1 =
73 {
74     FLOW_TO_SERVER | FLOW_ESTABLISHED
75 };
76 
77 static RuleOption option1 =
78 {
79     OPTION_TYPE_FLOWFLAGS,
80     { &flowflags1 }
81 };
82 
83 static ContentInfo content1 =
84 {                           /* Content */
85     (u_int8_t *)"|01|",                 /* pattern */
86     1,                      /* depth */
87     2,                      /* offset */
88     CONTENT_NOCASE | CONTENT_FAST_PATTERN, /* Flags */
89     NULL,                   /* Holder for Boyer Ptr */
90     NULL,
91     0, /* byteform length */
92     0, /* increment length */
93     0,                      /* holder for fp offset */
94     0,                      /* holder for fp length */
95     0,                      /* holder for fp only */
96     NULL, // offset_refId
97     NULL, // depth_refId
98     NULL, // offset_location
99     NULL  // depth_location
100 };
101 
102 static RuleOption option2 =
103 {
104     OPTION_TYPE_CONTENT,
105     { &content1 }
106 };
107 
108 static ByteData byte1 =
109 {                           /* Byte test */
110     2,                      /* bytes */
111     CHECK_GT,          /* operator */
112     0,                      /* value to compare against */
113     6,                      /* offset */
114     0,                      /* multiplier */
115     EXTRACT_AS_BYTE | CONTENT_BUF_RAW,                      /* flags */
116     0, /* offset */
117     NULL, // offset_refId
118     NULL, // value_refId
119     NULL, // offset_location
120     NULL  // value_location
121 };
122 
123 static RuleOption option3 =
124 {
125     OPTION_TYPE_BYTE_TEST,
126     { &byte1 }
127 };
128 
129 static ByteData byte2 =
130 {                           /* Byte test */
131     2,                      /* bytes */
132     CHECK_NEQ,         /* operator */
133     0,                      /* value to compare against */
134     8,                      /* offset */
135     0,                      /* multiplier */
136     EXTRACT_AS_BYTE | CONTENT_BUF_RAW,                      /* flags */
137     0, /* offset */
138     NULL, // offset_refId
139     NULL, // value_refId
140     NULL, // offset_location
141     NULL  // value_location
142 };
143 
144 static RuleOption option4 =
145 {
146     OPTION_TYPE_BYTE_TEST,
147     { &byte2 }
148 };
149 
150 static ByteData byte3 =
151 {                           /* Byte test */
152     2,                      /* bytes */
153     CHECK_NEQ,         /* operator */
154     16,                     /* value to compare against */
155     8,                      /* offset */
156     0,                      /* multiplier */
157     EXTRACT_AS_BYTE | CONTENT_BUF_RAW,                      /* flags */
158     0, /* offset */
159     NULL, // offset_refId
160     NULL, // value_refId
161     NULL, // offset_location
162     NULL  // value_location
163 };
164 
165 static RuleOption option5 =
166 {
167     OPTION_TYPE_BYTE_TEST,
168     { &byte3 }
169 };
170 
171 static ByteData byte4 =
172 {                           /* Byte test */
173     2,                      /* bytes */
174     CHECK_GT,          /* operator */
175     20,                     /* value to compare against */
176     10,                     /* offset */
177     0,                      /* multiplier */
178     EXTRACT_AS_BYTE | CONTENT_BUF_RAW,                      /* flags */
179     0, /* offset */
180     NULL, // offset_refId
181     NULL, // value_refId
182     NULL, // offset_location
183     NULL  // value_location
184 };
185 
186 static RuleOption option6 =
187 {
188     OPTION_TYPE_BYTE_TEST,
189     { &byte4 }
190 };
191 
192 static ContentInfo content2 =
193 {                           /* Content */
194     (u_int8_t *)"|8F|",
195     1,                      /* depth */
196     11,                     /* offset */
197     CONTENT_RELATIVE | CONTENT_BUF_NORMALIZED,           /* Flags */
198     NULL,                   /* Holder for Boyer Ptr */
199     NULL,
200     0, /* byteform length */
201     0, /* increment length */
202     0,                      /* holder for fp offset */
203     0,                      /* holder for fp length */
204     0,                      /* holder for fp only */
205     NULL, // offset_refId
206     NULL, // depth_refId
207     NULL, // offset_location
208     NULL  // depth_location
209 };
210 
211 static RuleOption option7 =
212 {
213     OPTION_TYPE_CONTENT,
214     { &content2 }
215 };
216 
217 static ByteData byte5 =
218 {                           /* Byte test */
219     2,                      /* bytes */
220     CHECK_GT,          /* operator */
221     32768,                  /* value to compare against */
222     0,                      /* offset */
223     0,                      /* multiplier */
224     EXTRACT_AS_BYTE | CONTENT_RELATIVE | CONTENT_BUF_RAW,       /* flags */
225     0, /* offset */
226     NULL, // offset_refId
227     NULL, // value_refId
228     NULL, // offset_location
229     NULL  // value_location
230 };
231 
232 static RuleOption option8 =
233 {
234     OPTION_TYPE_BYTE_TEST,
235     { &byte5 }
236 };
237 
238 static RuleOption *options[] =
239 {
240     &option1,
241     &option2,
242     &option3,
243     &option4,
244     &option5,
245     &option6,
246     &option7,
247     &option8,
248     NULL
249 };
250 
251 Rule sid2519 =
252 {
253     /* A skeleton rule generated from the GUI contains user configured
254      * IP & Port info */
255     {                               /* IP Info */
256         IPPROTO_TCP,                  /* Protocol */
257         EXTERNAL_NET,                 /* SRC IP -- pulled fr skeleton rule */
258         ANY_PORT,                     /* SRC Port -- pulled fr skeleton rule */
259         0,                            /* uni-directional */
260         SMTP_SERVERS,                 /* DST IP -- pulled fr skeleton rule */
261         "465",                          /* DST Port -- pulled fr skeleton rule */
262     },
263 
264     {                               /* Rule Information */
265         RULE_GID,                       /* Gen ID */
266         2519,                           /* Sig ID */
267         9,                              /* Rev */
268 
269         "attempted-admin",              /* classification */
270         0,                              /* Hard Coded Priority (overrides
271                                            class priority if non-0) */
272         "SMTP Client_Hello overflow attempt", /* message */
273         refs,                           /* References */
274         NULL /* metadata */
275     },
276     options,                            /* Options */
277     NULL,                               /* Use internal eval func */
278     0,                                  /* Not initialized */
279     0,                                  /* Rule option count, used internally */
280     0,                                  /* Flag with no alert, used internally */
281     NULL /* ptr to internal data... setup during rule registration */
282 };
283 
sid2519Eval(void * p)284 int sid2519Eval(void *p)
285 {
286     //const u_int8_t *uri_cur = 0;
287     const u_int8_t *norm_cur = 0;
288     if (checkFlow(p, sid2519.options[0]->option_u.flowFlags) )
289     {
290         if (contentMatch(p, sid2519.options[1]->option_u.content, &norm_cur)>0)
291         {
292             if(byteTest(p, sid2519.options[2]->option_u.byte, norm_cur))
293             {
294                 if(byteTest(p, sid2519.options[3]->option_u.byte, norm_cur))
295                 {
296                     if(byteTest(p, sid2519.options[4]->option_u.byte, norm_cur))
297                     {
298                         if(byteTest(p, sid2519.options[5]->option_u.byte, norm_cur))
299                         {
300                             if (contentMatch(p, sid2519.options[6]->option_u.content, &norm_cur)>0)
301                             {
302                                 if(byteTest(p, sid2519.options[7]->option_u.byte, norm_cur))
303                                 {
304 
305                                     return RULE_MATCH;
306                                 }
307                             }
308                         }
309                     }
310                 }
311             }
312         }
313     }
314     return RULE_NOMATCH;
315 }
316