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