2
* Copyright (C) 2011-2013 Sourcefire, Inc.
4
* The code is based on Flasm, command line assembler & disassembler of Flash
5
* ActionScript bytecode Copyright (c) 2001 Opaque Industries, (c) 2002-2007
6
* Igor Kogan, (c) 2005 Wang Zhen. All rights reserved.
8
* Redistribution and use in source and binary forms, with or without modification,
9
* are permitted provided that the following conditions are met:
11
* - Redistributions of source code must retain the above copyright notice, this list
12
* of conditions and the following disclaimer.
13
* - Redistributions in binary form must reproduce the above copyright notice, this
14
* list of conditions and the following disclaimer in the documentation and/or other
15
* materials provided with the distribution.
16
* - Neither the name of the Opaque Industries nor the names of its contributors may
17
* be used to endorse or promote products derived from this software without specific
18
* prior written permission.
20
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
23
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
25
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
28
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
#include "clamav-config.h"
37
#include <sys/types.h>
52
#define EC16(v) le16_to_host(v)
53
#define EC32(v) le32_to_host(v)
57
if(fmap_readn(map, &get_c, offset, sizeof(get_c)) == sizeof(get_c)) { \
59
bitbuf = (unsigned int) get_c; \
60
offset += sizeof(get_c); \
62
cli_errmsg("cli_scanswf: INITBITS: Can't read file\n"); \
67
#define GETBITS(v, n) \
71
while(getbits_n > bitpos) { \
72
getbits_n -= bitpos; \
73
bits |= bitbuf << getbits_n; \
74
if(fmap_readn(map, &get_c, offset, sizeof(get_c)) == sizeof(get_c)) { \
75
bitbuf = (unsigned int) get_c; \
77
offset += sizeof(get_c); \
79
cli_errmsg("cli_scanswf: GETBITS: Can't read file\n"); \
83
bitpos -= getbits_n; \
84
bits |= bitbuf >> bitpos; \
85
bitbuf &= 0xff >> (8 - bitpos); \
91
if(fmap_readn(map, &get_c, offset, sizeof(get_c)) == sizeof(get_c)) { \
92
getword_1 = (unsigned int) get_c; \
93
offset += sizeof(get_c); \
95
cli_errmsg("cli_scanswf: GETWORD: Can't read file\n"); \
98
if(fmap_readn(map, &get_c, offset, sizeof(get_c)) == sizeof(get_c)) { \
99
getword_2 = (unsigned int) get_c; \
100
offset += sizeof(get_c); \
102
cli_errmsg("cli_scanswf: GETWORD: Can't read file\n"); \
105
v = (uint16_t)(getword_1 & 0xff) | ((getword_2 & 0xff) << 8); \
108
#define GETDWORD(v) \
110
GETWORD(getdword_1); \
111
GETWORD(getdword_2); \
112
v = (uint32_t)(getdword_1 | (getdword_2 << 16)); \
115
struct swf_file_hdr {
121
static int scancws(cli_ctx *ctx, struct swf_file_hdr *hdr)
124
char inbuff[FILEBUFF], outbuff[FILEBUFF];
125
fmap_t *map = *ctx->fmap;
126
int offset = 8, ret, zret, outsize = 8, count;
130
if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd)) != CL_SUCCESS) {
131
cli_errmsg("scancws: Can't generate temporary file\n");
135
hdr->signature[0] = 'F';
136
if(cli_writen(fd, hdr, sizeof(struct swf_file_hdr)) != sizeof(struct swf_file_hdr)) {
137
cli_errmsg("scancws: Can't write to file %s\n", tmpname);
139
if(cli_unlink(tmpname)) {
148
stream.next_in = inbuff;
149
stream.next_out = outbuff;
150
stream.zalloc = (alloc_func) NULL;
151
stream.zfree = (free_func) NULL;
152
stream.opaque = (voidpf) 0;
153
stream.avail_out = FILEBUFF;
155
zret = inflateInit(&stream);
157
cli_errmsg("scancws: inflateInit() failed\n");
159
if(cli_unlink(tmpname)) {
168
if(stream.avail_in == 0) {
169
stream.next_in = inbuff;
170
ret = fmap_readn(map, inbuff, offset, FILEBUFF);
172
cli_errmsg("scancws: Error reading SWF file\n");
174
if(cli_unlink(tmpname)) {
183
stream.avail_in = ret;
186
zret = inflate(&stream, Z_SYNC_FLUSH);
187
count = FILEBUFF - stream.avail_out;
189
if(cli_checklimits("SWF", ctx, outsize + count, 0, 0) != CL_SUCCESS)
191
if(cli_writen(fd, outbuff, count) != count) {
192
cli_errmsg("scancws: Can't write to file %s\n", tmpname);
194
if(cli_unlink(tmpname)) {
203
stream.next_out = outbuff;
204
stream.avail_out = FILEBUFF;
205
} while(zret == Z_OK);
207
if((zret != Z_STREAM_END && zret != Z_OK) || (zret = inflateEnd(&stream)) != Z_OK) {
208
cli_infomsg(ctx, "scancws: Error decompressing SWF file\n");
210
if(cli_unlink(tmpname)) {
217
cli_dbgmsg("SWF: Decompressed to %s, size %d\n", tmpname, outsize);
219
ret = cli_magic_scandesc(fd, ctx);
222
if(!ctx->engine->keeptmp) {
223
if(cli_unlink(tmpname)) {
232
static const char *tagname(tag_id id)
236
for(i = 0; tag_names[i].name; i++)
237
if(tag_names[i].id == id)
238
return tag_names[i].name;
242
int cli_scanswf(cli_ctx *ctx)
244
struct swf_file_hdr file_hdr;
245
fmap_t *map = *ctx->fmap;
246
unsigned int bitpos, bitbuf, getbits_n, nbits, getword_1, getword_2, getdword_1, getdword_2;
250
unsigned int val, foo, tag_hdr, tag_type, tag_len;
251
unsigned long int bits;
253
cli_dbgmsg("in cli_scanswf()\n");
255
if(fmap_readn(map, &file_hdr, offset, sizeof(file_hdr)) != sizeof(file_hdr)) {
256
cli_dbgmsg("SWF: Can't read file header\n");
259
offset += sizeof(file_hdr);
261
if(!strncmp(file_hdr.signature, "CWS", 3)) {
262
cli_dbgmsg("SWF: Compressed file\n");
263
return scancws(ctx, &file_hdr);
264
} else if(!strncmp(file_hdr.signature, "FWS", 3)) {
265
cli_dbgmsg("SWF: Uncompressed file\n");
267
cli_dbgmsg("SWF: Not a SWF file\n");
271
cli_dbgmsg("SWF: Version: %u\n", file_hdr.version);
272
cli_dbgmsg("SWF: File size: %u\n", EC32(file_hdr.filesize));
277
GETBITS(foo, nbits); /* xMin */
278
GETBITS(foo, nbits); /* xMax */
279
GETBITS(foo, nbits); /* yMin */
280
GETBITS(foo, nbits); /* yMax */
284
cli_dbgmsg("SWF: Frames total: %d\n", val);
286
while(offset < map->len) {
288
tag_type = tag_hdr >> 6;
291
tag_len = tag_hdr & 0x3f;
295
pt = tagname(tag_type);
296
cli_dbgmsg("SWF: %s\n", pt ? pt : "UNKNOWN TAG");
297
cli_dbgmsg("SWF: Tag length: %u\n", tag_len);
298
if (tag_len > map->len) {
299
cli_warnmsg("SWF: Invalid tag length.\n");
302
if ((offset + tag_len) < offset) {
303
cli_warnmsg("SWF: Tag length too large.\n");
312
case TAG_SCRIPTLIMITS: {
313
unsigned int recursion, timeout;
316
cli_dbgmsg("SWF: scriptLimits recursion %u timeout %u\n", recursion, timeout);
320
case TAG_FILEATTRIBUTES:
322
cli_dbgmsg("SWF: File attributes:\n");
323
if(val & SWF_ATTR_USENETWORK)
324
cli_dbgmsg(" * Use network\n");
325
if(val & SWF_ATTR_RELATIVEURLS)
326
cli_dbgmsg(" * Relative URLs\n");
327
if(val & SWF_ATTR_SUPPRESSCROSSDOMAINCACHE)
328
cli_dbgmsg(" * Suppress cross domain cache\n");
329
if(val & SWF_ATTR_ACTIONSCRIPT3)
330
cli_dbgmsg(" * ActionScript 3.0\n");
331
if(val & SWF_ATTR_HASMETADATA)
332
cli_dbgmsg(" * Has metadata\n");
333
if(val & SWF_ATTR_USEDIRECTBLIT)
334
cli_dbgmsg(" * Use hardware acceleration\n");
335
if(val & SWF_ATTR_USEGPU)
336
cli_dbgmsg(" * Use GPU\n");