1 #include "config.h"
2 #include <razorback/visibility.h>
3 #include <razorback/api.h>
4 #include <razorback/log.h>
5 #include <razorback/uuids.h>
6 #include <razorback/block.h>
7 #include <razorback/hash.h>
8 #include <razorback/config_file.h>
9 #include <razorback/judgment.h>
10 #include <razorback/metadata.h>
11
12
13 #include "swf_scanner.h"
14
15 #define SWF_SCANNER_CONFIG "swf_scanner.conf"
16 UUID_DEFINE(FLASH, 0x20, 0xf7, 0x53, 0x80, 0xaf, 0xb0, 0x11, 0xdf, 0x86, 0x6f, 0x7b, 0x86, 0xc6, 0x49, 0x59, 0x6b);
17 static uuid_t sg_uuidNuggetId;
18 static conf_int_t sg_initThreads = 0;
19 static conf_int_t sg_maxThreads = 0;
20
21 struct RazorbackContext *sg_pContext = NULL;
22
23 bool processDeferredList (struct DeferredList *p_pDefferedList);
24 DECL_INSPECTION_FUNC(scanSWF);
25
26 static struct RazorbackInspectionHooks sg_InspectionHooks ={
27 scanSWF,
28 processDeferredList,
29 NULL,
30 NULL
31 };
32
33 RZBConfKey_t sg_Config[] = {
34 {"NuggetId", RZB_CONF_KEY_TYPE_UUID, &sg_uuidNuggetId, NULL},
35 {"Threads.Initial", RZB_CONF_KEY_TYPE_INT, &sg_initThreads, NULL },
36 {"Threads.Max", RZB_CONF_KEY_TYPE_INT, &sg_maxThreads, NULL },
37 {NULL, RZB_CONF_KEY_TYPE_END, NULL, NULL}
38 };
39
processDeferredList(struct DeferredList * p_pDefferedList)40 bool processDeferredList (struct DeferredList *p_pDefferedList)
41 {
42 return true;
43 }
44
45
46
47 static void sendWarnings(struct EventId *eventId, struct BlockId *blockId, ErrorCode errCode);
48
49 #ifdef VERBOSE
50
printRECT(RECT * struct_rect,char * prefix)51 static void printRECT(RECT *struct_rect, char *prefix)
52 {
53 printf("%sRECT.NBits [%u]\n", prefix, struct_rect->Nbits);
54 printf("%sRECT.Xmin [%u]\n", prefix, struct_rect->Xmin);
55 printf("%sRECT.Xmax [%u]\n", prefix, struct_rect->Xmax);
56 printf("%sRECT.Ymin [%u]\n", prefix, struct_rect->Ymin);
57 printf("%sRECT.Ymax [%u]\n", prefix, struct_rect->Ymax);
58 }
59
printHEADER(SWFFileInfo * swffile)60 static void printHEADER(SWFFileInfo *swffile)
61 {
62 printf("SWF.HEADER.Signature [%c%c%c]\n", swffile->header.Signature[0], swffile->header.Signature[1], swffile->header.Signature[2]);
63 printf("SWF.HEADER.Version [%d]\n", swffile->header.Version);
64 printf("SWF.HEADER.FileLength [%d]\n", swffile->header.FileLength);
65 printf("SWF.HEADER.FrameSize\n");
66 printRECT(&(swffile->header.FrameSize), "-- ");
67 printf("SWF.HEADER.FrameRate [%d]\n", swffile->header.FrameRate);
68 printf("SWF.HEADER.FrameCount [%d]\n", swffile->header.FrameCount);
69 }
70
printTAGs(TAGList * tags,uint32_t level)71 static void printTAGs(TAGList *tags, uint32_t level)
72 {
73 TAG *cur_tag;
74 uint16_t tag_type;
75 uint32_t tag_index = 0;
76
77 char *prefix;
78
79 if (level == 0)
80 prefix = "";
81 else
82 prefix = "--- ";
83
84 cur_tag = tags->tag_head;
85
86 while (cur_tag != NULL)
87 {
88 tag_type = cur_tag->TagCode;
89
90 if (tag_type < MAX_TYPE_CODE)
91 printf("%sTAG[%d].TagCode [%d][%s]\n", prefix, tag_index, tag_type, TypeName[tag_type]);
92 else
93 printf("%sTAG[%d].TagCode [%d]\n", prefix, tag_index, tag_type);
94
95 printf("%sTAG[%d].Length [%d]\n", prefix, tag_index, cur_tag->Length);
96
97 cur_tag = cur_tag->next;
98 tag_index++;
99
100 if (tag_type == TYPE_DefineSprite)
101 printTAGs(&(cur_tag->tags), 1);
102 }
103 }
104
105 #endif
106
107 /* Decompression function for 'CWS' Flash files. It decompress an entire file at once */
108
109 #define CHUNK 0x40000 // 256K
110
decompressSWF(SWFFileInfo * swffile,uint8_t * cursor,uint32_t size)111 static ErrorCode decompressSWF(SWFFileInfo *swffile, uint8_t *cursor, uint32_t size)
112 {
113 z_stream stream;
114 int ret;
115 int count_newbuff = 0;
116 uint32_t file_length;
117
118 stream.next_in = cursor + 8;
119 stream.avail_in = size - 8;
120
121 stream.zalloc = Z_NULL;
122 stream.zfree = Z_NULL;
123 stream.opaque = Z_NULL;
124
125 stream.avail_out = 0;
126 inflateInit(&stream);
127
128 swffile->decompressed_data = (uint8_t *)malloc(CHUNK);
129 if (swffile->decompressed_data == NULL)
130 return SWF_ERROR_MEMORY;
131
132 count_newbuff++;
133 memcpy(swffile->decompressed_data, &(swffile->header), 4);
134
135 // The first 8 bytes of SWF file is not compressed
136 stream.avail_out = CHUNK - 8;
137 stream.next_out = swffile->decompressed_data + 8;
138
139 while (1)
140 {
141 if (!stream.avail_out)
142 {
143 count_newbuff++;
144 swffile->decompressed_data = (Bytef *)realloc(swffile->decompressed_data, CHUNK * count_newbuff);
145 if (swffile->decompressed_data == NULL)
146 return SWF_ERROR_MEMORY;
147
148 stream.next_out = swffile->decompressed_data + ((count_newbuff - 1) * CHUNK);
149 stream.avail_out = CHUNK;
150 }
151
152 if (stream.next_in)
153 ret = inflate(&stream, Z_NO_FLUSH);
154 else
155 ret = inflate(&stream, Z_FINISH);
156
157 if (ret != Z_OK && ret != Z_STREAM_END)
158 break;
159
160 if (ret == Z_STREAM_END)
161 {
162 ret = inflateEnd(&stream);
163
164 file_length = stream.total_out + 8; // 8 bytes = header.Signature, header.Version, header.FileLength
165
166 // store the size of decompressed data to the file length field in the buffer
167 *(swffile->decompressed_data + 4) = (uint8_t)file_length;
168 *(swffile->decompressed_data + 5) = (uint8_t)(file_length >> 8);
169 *(swffile->decompressed_data + 6) = (uint8_t)(file_length >> 16);
170 *(swffile->decompressed_data + 7) = (uint8_t)(file_length >> 24);
171
172 // use SWF scanner's own memory instead of the memory provided by the dispatcher
173 swffile->bof = swffile->decompressed_data;
174 swffile->eof = swffile->decompressed_data + file_length;
175
176 break;
177 }
178 }
179
180 if (ret != Z_OK)
181 {
182 free(swffile->decompressed_data);
183 swffile->decompressed_data = NULL;
184 swffile->compressed = 0;
185
186 return SWF_ERROR_DECOMPRESSION;
187 }
188
189 return SWF_OK;
190 }
191
createTAG(TAGList * tag_list)192 static ErrorCode createTAG(TAGList *tag_list)
193 {
194 TAG *new_tag;
195
196 new_tag = (TAG *)malloc(sizeof(TAG));
197
198 if (new_tag == NULL)
199 return SWF_ERROR_MEMORY;
200
201 memset(new_tag, 0, sizeof(TAG));
202
203 if (tag_list->tag_head == NULL)
204 {
205 tag_list->tag_head = new_tag;
206 tag_list->tag_tail = new_tag;
207 }
208 else
209 {
210 ((TAG *)tag_list->tag_tail)->next = new_tag;
211 new_tag->prev = tag_list->tag_tail;
212
213 tag_list->tag_tail = new_tag;
214 }
215
216 return SWF_OK;
217 }
218
freeTAGs(TAGList * tags)219 static void freeTAGs(TAGList *tags)
220 {
221 TAG *tag_head;
222 TAG *tag_delete;
223
224 tag_head = tags->tag_head;
225
226 while (tag_head != NULL)
227 {
228 tag_delete = tag_head;
229 tag_head = tag_head->next;
230
231 tag_delete->prev = NULL;
232 tag_delete->next = NULL;
233
234 if (tag_delete->TagCode == TYPE_DefineSprite)
235 freeTAGs(&(tag_delete->tags));
236
237 free(tag_delete);
238 }
239
240 tags->tag_head = NULL;
241 tags->tag_tail = NULL;
242 }
243
244 // Make sure Nbits <= 31
245
readVarBits(uint8_t ** cursor,uint8_t Nbits,uint8_t * bit_offset)246 static uint32_t readVarBits(uint8_t **cursor, uint8_t Nbits, uint8_t *bit_offset)
247 {
248 uint32_t multibits_value; // the most significant bit is the leftmost bit
249
250 uint8_t i;
251 uint8_t *tmp_cursor = *cursor;
252 uint8_t tmp_offset = *bit_offset;
253
254 multibits_value = 0;
255 for (i = 0; i < Nbits; i++)
256 {
257 if (*tmp_cursor & (0x80 >> (tmp_offset % 8)))
258 multibits_value |= 1;
259
260 multibits_value <<= 1;
261 tmp_offset++;
262
263 if ((tmp_offset % 8) == 0)
264 tmp_cursor++;
265 }
266
267 multibits_value >>= 1; // to cancel the last left shift
268
269 *cursor = tmp_cursor;
270 *bit_offset = tmp_offset;
271
272 return multibits_value;
273 }
274
parseRECT(SWFFileInfo * swffile,uint8_t ** cursor)275 static ErrorCode parseRECT(SWFFileInfo *swffile, uint8_t **cursor)
276 {
277 uint8_t Nbits;
278 uint8_t bit_offset;
279 uint16_t rect_size;
280
281 uint8_t *tmp_cursor = *cursor;
282
283 if (tmp_cursor + 1 > swffile->eof)
284 return SWF_ERROR_NODATA;
285
286 Nbits = (uint8_t)((*tmp_cursor & 0xF8) >> 3); // read left most 5 bits
287 rect_size = (uint16_t)ceil((double)(5 + (Nbits * 4))/8) ; // total in bytes
288
289 if (tmp_cursor + rect_size > swffile->eof)
290 return SWF_ERROR_NODATA;
291
292 swffile->header.FrameSize.Nbits = Nbits;
293
294 // after Nbits field
295 bit_offset = 5;
296 swffile->header.FrameSize.Xmin = readVarBits(&tmp_cursor, Nbits, &bit_offset);
297 swffile->header.FrameSize.Xmax = readVarBits(&tmp_cursor, Nbits, &bit_offset);
298 swffile->header.FrameSize.Ymin = readVarBits(&tmp_cursor, Nbits, &bit_offset);
299 swffile->header.FrameSize.Ymax = readVarBits(&tmp_cursor, Nbits, &bit_offset);
300
301 *cursor += rect_size;
302
303 return SWF_OK;
304 }
305
parseHEADER(SWFFileInfo * swffile,uint8_t ** cursor)306 static ErrorCode parseHEADER(SWFFileInfo *swffile, uint8_t **cursor)
307 {
308 uint8_t *tmp_cursor = *cursor;
309
310 if (tmp_cursor + 12 > swffile->eof)
311 {
312 rzb_log(LOG_DEBUG, "Not enough data to parse SWF header");
313 return SWF_ERROR_NODATA;
314 }
315
316 tmp_cursor += 4;
317 swffile->header.FileLength = READ_LITTLE_32(tmp_cursor);
318 tmp_cursor += 4;
319
320 #if 0
321 // File length does not follow the specification all the time
322 if (swffile->header.FileLength != (swffile->eof - swffile->bof))
323 {
324 DEBUG_SWF(printf("swffile->header.FileLength [0x%08x] actual [0x%08x]\n",
325 swffile->header.FileLength, (swffile->eof - swffile->bof));)
326 return SWF_ERROR_INVALID_FILELENGTH;
327 }
328 #endif
329
330 parseRECT(swffile, &tmp_cursor);
331
332 if (tmp_cursor + 4 > swffile->eof)
333 return SWF_ERROR_NODATA;
334
335 swffile->header.FrameRate = READ_LITTLE_16(tmp_cursor);
336 tmp_cursor += 2;
337 swffile->header.FrameCount = READ_LITTLE_16(tmp_cursor);
338 tmp_cursor += 2;
339
340 *cursor = tmp_cursor;
341
342 VERBOSE_SWF(printHEADER(swffile);)
343
344 return SWF_OK;
345 }
346
parseTAG(TAGList * tag_list,uint8_t ** cursor,uint8_t * end_to_parse)347 static ErrorCode parseTAG(TAGList *tag_list, uint8_t **cursor, uint8_t *end_to_parse)
348 {
349 uint8_t *tmp_cursor = *cursor;
350 uint16_t type_and_length;
351 uint16_t tag_type;
352 uint32_t tag_length;
353 ErrorCode errCode;
354
355 if (tmp_cursor + 2 > end_to_parse)
356 return SWF_ERROR_NODATA;
357
358 type_and_length = READ_LITTLE_16(tmp_cursor);
359 tmp_cursor += 2;
360
361 tag_type = (uint16_t)((type_and_length & 0xFFC0) >> 6);
362 tag_length = type_and_length & 0x003F;
363
364 if (tag_length == 0x3F)
365 {
366 if (tmp_cursor + 4 > end_to_parse)
367 return SWF_ERROR_NODATA;
368
369 tag_length = READ_LITTLE_32(tmp_cursor);
370 tmp_cursor += 4;
371 }
372
373 if (tmp_cursor + tag_length > end_to_parse)
374 return SWF_ERROR_NODATA;
375
376 if (tmp_cursor + tag_length < tmp_cursor) // integer overflow
377 return SWF_ERROR_INVALID_TAGLENGTH;
378
379 // Once a tag structure is allocated, there must be tag_length data
380 errCode = createTAG(tag_list);
381 if (errCode != SWF_OK)
382 return errCode;
383
384 ((TAG *)tag_list->tag_tail)->TagCode = tag_type;
385 ((TAG *)tag_list->tag_tail)->Length = tag_length;
386 ((TAG *)tag_list->tag_tail)->tag_start = *cursor;
387 ((TAG *)tag_list->tag_tail)->tag_data = tmp_cursor;
388
389 *cursor = tmp_cursor + tag_length;
390
391 return SWF_OK;
392 }
393
parseDefineSpriteTAG(TAG * definesprite_tag)394 static ErrorCode parseDefineSpriteTAG(TAG *definesprite_tag)
395 {
396 ErrorCode errCode = SWF_OK;
397 uint8_t *tag_cursor = definesprite_tag->tag_data;
398 uint8_t *end_of_tag = tag_cursor + definesprite_tag->Length;
399
400 // In order to include tag array,
401 // the length of DefineSprite tag should be bigger than or equal to 6
402 if (definesprite_tag->Length < 6)
403 return SWF_ERROR_INVALID_TAGLENGTH;
404
405 tag_cursor += 4; // to skip over Sprite ID and FrameCount fields
406
407 while (errCode == SWF_OK && tag_cursor < end_of_tag)
408 errCode = parseTAG(&(definesprite_tag->tags), &tag_cursor, end_of_tag);
409
410 return errCode;
411 }
412
parseSWF(SWFFileInfo * swffile,uint8_t * cursor,uint32_t size)413 static ErrorCode parseSWF(SWFFileInfo *swffile, uint8_t *cursor, uint32_t size)
414 {
415 ErrorCode errCode;
416
417 if ((*cursor == 'F' || *cursor == 'C')
418 && *(cursor + 1) == 'W' && *(cursor + 2) == 'S')
419 {
420 swffile->header.Signature[0] = 'F';
421 swffile->header.Signature[1] = 'W';
422 swffile->header.Signature[2] = 'S';
423
424 if (*cursor == 'C')
425 swffile->compressed = 1;
426 }
427 else
428 return SWF_ERROR_INVALID_SIG;
429
430 swffile->header.Version = *(cursor + 3);
431
432 if (swffile->compressed)
433 {
434 if (decompressSWF(swffile, cursor, size) == SWF_OK)
435 cursor = swffile->decompressed_data;
436 else
437 return SWF_ERROR_DECOMPRESSION;
438 }
439
440 errCode = parseHEADER(swffile, &cursor);
441
442 // parseHEADER returns either SWF_OK or SWF_ERROR_NODATA
443 // We don't need to parse further in this case if SWF_ERROR_NODATA takes place in the header
444 if (errCode != SWF_OK)
445 return errCode;
446
447 while (errCode == SWF_OK && cursor < swffile->eof)
448 {
449 errCode = parseTAG(&(swffile->tags), &cursor, swffile->eof);
450
451 if (errCode == SWF_OK && ((TAG *)swffile->tags.tag_tail)->TagCode == TYPE_DefineSprite)
452 errCode = parseDefineSpriteTAG(swffile->tags.tag_tail);
453 }
454
455
456 VERBOSE_SWF(printTAGs(&(swffile->tags), 0);)
457
458 return errCode;
459 }
460
scanActionRecords(TAG * action_tag,SWFDetectionID * detectID)461 static ErrorCode scanActionRecords(TAG *action_tag, SWFDetectionID *detectID)
462 {
463 uint8_t *action_cursor = action_tag->tag_data;
464 uint8_t *end_of_tag = action_tag->tag_data + action_tag->Length;
465
466 uint8_t action_code;
467 uint16_t action_length;
468
469 uint8_t *detect_cursor;
470
471 *detectID = SWFDetectionID_NONE;
472
473 while (action_cursor < end_of_tag)
474 {
475 action_code = *action_cursor;
476 action_cursor++;
477
478 if (action_code < 0x80)
479 continue;
480 else
481 {
482 if (action_cursor + 2 > end_of_tag)
483 return SWF_ERROR_NODATA;
484
485 action_length = READ_LITTLE_16(action_cursor);
486 action_cursor += 2;
487
488 if (action_code == ACTIONCODE_ActionDefineFunction || action_code == ACTIONCODE_ActionDefineFunction2)
489 {
490 detect_cursor = action_cursor;
491
492 while (*detect_cursor != '\0') detect_cursor++;
493
494 if (detect_cursor >= action_cursor + action_length)
495 {
496 *detectID = SWFDetectionID_CVE_2005_2628;
497 return SWF_OK;
498 }
499 }
500
501 action_cursor += action_length;
502 }
503 }
504
505 return SWF_OK;
506 }
507
scanTAGs(TAGList * tags,SWFDetectionID * detectID,uint16_t frame_count)508 static ErrorCode scanTAGs(TAGList *tags, SWFDetectionID *detectID, uint16_t frame_count)
509 {
510 TAG *cur_tag;
511 uint8_t *detect_cursor;
512 uint8_t *tmp_cursor;
513 ErrorCode sub_error;
514
515 uint32_t endtag_found = 0;
516 uint32_t count_showframe = 0; // for CVE-2007-5400
517
518 uint16_t definesprite_framecount;
519
520 *detectID = SWFDetectionID_NONE;
521 cur_tag = tags->tag_head;
522
523 while (cur_tag != NULL)
524 {
525 /* CVE-2007-0071 */
526 if (cur_tag->TagCode == TYPE_DefineSceneAndFrameLabelData)
527 {
528 detect_cursor = cur_tag->tag_data;
529
530 if (cur_tag->Length >= 5)
531 {
532 if (detect_cursor[0] & 0x80 && detect_cursor[1] & 0x80
533 && detect_cursor[2] & 0x80 && detect_cursor[3] & 0x80
534 && detect_cursor[4] & 0x08)
535 {
536
537 rzb_log(LOG_DEBUG, "SceneCount[0] = 0x%02x, [1] = 0x%02x, [2] = 0x%02x, [3] = 0x%02x, [4] = 0x%02x\n",
538 detect_cursor[0], detect_cursor[1], detect_cursor[2], detect_cursor[3], detect_cursor[4]);
539
540 *detectID = SWFDetectionID_CVE_2007_0071;
541 return SWF_OK;
542 }
543 }
544 else
545 return SWF_ERROR_NODATA;
546 }
547
548 /* CVE-2007-5400 */
549 /* some compreessed SWF file ends up with extra data after End tag, we need to ignore them */
550 if (cur_tag->TagCode == TYPE_ShowFrame && !endtag_found)
551 count_showframe++;
552
553 if (cur_tag->TagCode == TYPE_End)
554 endtag_found = 1;
555
556 /* CVE-2005-2628 */
557 if (cur_tag->TagCode == TYPE_DoAction)
558 {
559 sub_error = scanActionRecords(cur_tag, detectID);
560
561 if (sub_error != SWF_OK || *detectID != SWFDetectionID_NONE)
562 return sub_error;
563 }
564
565 if (cur_tag->TagCode == TYPE_DefineSprite && cur_tag->tags.tag_head != NULL)
566 {
567 if (cur_tag->Length >= 6) // 6 is minium size of DefineSprite
568 {
569 tmp_cursor = cur_tag->tag_data + 2;
570 definesprite_framecount = READ_LITTLE_16(tmp_cursor);
571
572 sub_error = scanTAGs(&(cur_tag->tags), detectID, definesprite_framecount);
573
574 if (sub_error != SWF_OK || *detectID != SWFDetectionID_NONE)
575 return sub_error;
576 }
577 }
578
579 cur_tag = cur_tag->next;
580 }
581
582 /* CVE-2007-5400 */
583 /* CVE-2006-0323 */
584 /* Remove these checks because of false positives, functionality pushed to reworked flash parser.
585 if (frame_count != count_showframe)
586 {
587 rzb_log(LOG_ERR,"Header.FrameCount [0x%08x], actual count [0x%08x]\n", frame_count, count_showframe);
588 *detectID = SWFDetectionID_CVE_2007_5400;
589 return SWF_OK;
590 }
591 */
592
593 return SWF_OK;
594 }
595
596 /* any anomalies found during parsing, report them */
sendWarnings(struct EventId * eventId,struct BlockId * blockId,ErrorCode errCode)597 static void sendWarnings(struct EventId *eventId, struct BlockId *blockId, ErrorCode errCode)
598 {
599 const char *warning_msg;
600 struct Judgment *judgment;
601 if ((judgment = Judgment_Create(eventId, blockId)) == NULL)
602 {
603 rzb_log(LOG_ERR, "SWF Scanner: Failed to allocate judgment");
604 return;
605 }
606 switch (errCode)
607 {
608 case SWF_ERROR_INVALID_SIG:
609 warning_msg = "Warning: SWF signature is not valid";
610 break;
611 case SWF_ERROR_NODATA:
612 case SWF_ERROR_INVALID_TAGLENGTH:
613 warning_msg = "Warning: The inspected file may be truncated";
614 break;
615 case SWF_ERROR_MEMORY:
616 warning_msg = "Warning: There is not memory related error";
617 break;
618 case SWF_ERROR_DECOMPRESSION:
619 warning_msg = "Warning: Decompression failed";
620 break;
621 default:
622 warning_msg = "Warning: unhandled warning";
623 }
624 judgment->Set_SfFlags = SF_FLAG_DODGY;
625 judgment->iPriority = 2;
626 if (asprintf((char **)&judgment->sMessage, "%s", warning_msg) == -1)
627 {
628 rzb_log(LOG_ERR, "SWF Scanner: Failed to allocate message");
629 Judgment_Destroy(judgment);
630 return;
631 }
632 Razorback_Render_Verdict(judgment);
633 }
634
sendDetectionResult(struct EventId * eventId,struct BlockId * blockId,SWFDetectionID detectID)635 static void sendDetectionResult(struct EventId *eventId, struct BlockId *blockId, SWFDetectionID detectID)
636 {
637 struct Judgment *judgment;
638 if (detectID >= SWFDetectionID_END)
639 {
640 rzb_log(LOG_ERR, "SWF Scanner: Invalid detection id");
641 return;
642 }
643 if ((judgment = Judgment_Create(eventId, blockId)) == NULL)
644 {
645 rzb_log(LOG_ERR, "SWF Scanner: Failed to allocate judgment");
646 return;
647 }
648 for (int i =0; i < DetectionResults[detectID]->cveCount; i++)
649 {
650 Metadata_Add_CVE(judgment->pMetaDataList, DetectionResults[detectID]->cve[i]);
651 }
652 for (int i =0; i < DetectionResults[detectID]->bidCount; i++)
653 {
654 Metadata_Add_BID(judgment->pMetaDataList, DetectionResults[detectID]->bid[i]);
655 }
656
657 judgment->iPriority = 1;
658 judgment->Set_SfFlags = SF_FLAG_BAD;
659 if (asprintf((char **)&judgment->sMessage, "%s", DetectionResults[detectID]->description) == -1)
660 {
661 rzb_log(LOG_ERR, "SWF Scanner: Failed to allocate message");
662 Judgment_Destroy(judgment);
663 return;
664 }
665 Razorback_Render_Verdict(judgment);
666 }
667
DECL_INSPECTION_FUNC(scanSWF)668 DECL_INSPECTION_FUNC(scanSWF)
669 {
670 SWFFileInfo swffile;
671 ErrorCode errCode;
672 SWFDetectionID detectID = SWFDetectionID_NONE;
673 unsigned char *cursor = block->data.pointer;
674 uint64_t size = block->pId->iLength;
675
676 if (cursor == NULL || size == 0 || size > 0x7FFFFFFF)
677 {
678 rzb_log(LOG_ERR, "SWF Scanner: Invalid data");
679 return JUDGMENT_REASON_ERROR;
680 }
681
682 memset(&swffile, 0, sizeof(SWFFileInfo));
683
684 swffile.bof = cursor;
685 if (cursor + size <= cursor)
686 {
687 rzb_log(LOG_ERR, "SWF Scanner: file size[0x%08x] is too big", size);
688 return JUDGMENT_REASON_ERROR;
689 }
690
691 swffile.eof = cursor + size;
692
693 errCode = parseSWF(&swffile, cursor, size);
694
695 if (errCode != SWF_OK)
696 sendWarnings(eventId, block->pId, errCode);
697
698 errCode = scanTAGs(&(swffile.tags), &detectID, swffile.header.FrameCount);
699
700 if (errCode != SWF_OK)
701 sendWarnings(eventId, block->pId, errCode);
702
703 /* if some legitimate tags are scanned */
704 if ( (swffile.tags.tag_head != NULL) &&
705 (detectID != SWFDetectionID_NONE))
706 {
707 sendDetectionResult(eventId, block->pId, detectID);
708 }
709
710 /* epilog */
711 freeTAGs(&(swffile.tags));
712
713 if (swffile.compressed)
714 free(swffile.decompressed_data);
715
716 return JUDGMENT_REASON_DONE;
717 }
718
719 SO_PUBLIC DECL_NUGGET_INIT
720 {
721 uuid_t list[1];
722
723 if (!readMyConfig(NULL, SWF_SCANNER_CONFIG, sg_Config))
724 return false;
725
726 if (!UUID_Get_UUID(DATA_TYPE_FLASH_FILE, UUID_TYPE_DATA_TYPE, list[0]))
727 {
728 rzb_log(LOG_ERR, "SWF Scanner: Failed to get SWF_FILE UUID");
729 return false;
730 }
731
732 uuid_t l_pTempUuid;
733 uuid_copy(l_pTempUuid, FLASH);
734
735 if ((sg_pContext = Razorback_Init_Inspection_Context (
736 sg_uuidNuggetId, l_pTempUuid, 1, list,
737 &sg_InspectionHooks, sg_initThreads, sg_maxThreads)) == NULL)
738 {
739 return false;
740 }
741 return true;
742 }
743
744 SO_PUBLIC DECL_NUGGET_SHUTDOWN
745 {
746 Razorback_Shutdown_Context(sg_pContext);
747 }
748
749