Browse code

libclamav/swf.c: scan images and binary blobs

Tomasz Kojm authored on 2011/03/30 23:02:41
Showing 3 changed files
... ...
@@ -1,3 +1,7 @@
1
+Wed Mar 30 16:02:00 CEST 2011 (tk)
2
+----------------------------------
3
+ * libclamav/swf.c: scan images and binary blobs
4
+
1 5
 Mon Mar 28 20:24:40 CEST 2011 (tk)
2 6
 ----------------------------------
3 7
  * libclamav: add skeleton code for SWF parser
... ...
@@ -221,14 +221,69 @@ static const char *tagname(tag_id id)
221 221
     return NULL;
222 222
 }
223 223
 
224
+static int dumpscan(fmap_t *map, unsigned int offset, unsigned int size, const char *obj, cli_ctx *ctx)
225
+{
226
+	int newfd, ret;
227
+	unsigned int bread, sum = 0;
228
+	char buff[FILEBUFF];
229
+	char *name;
230
+
231
+    if(!(name = cli_gentemp(ctx->engine->tmpdir)))
232
+	return CL_EMEM;
233
+
234
+    if((newfd = open(name, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
235
+	cli_errmsg("dumpscan: Can't create file %s\n", name);
236
+	free(name);
237
+	return CL_ECREAT;
238
+    }
239
+
240
+    while((bread = fmap_readn(map, buff, offset, sizeof(buff))) > 0) {
241
+	if(sum + bread >= size) {
242
+	    if(cli_writen(newfd, buff, size - sum) == -1) {
243
+		cli_errmsg("dumpscan: Can't write to %s\n", name);
244
+		cli_unlink(name);
245
+		free(name);
246
+		close(newfd);
247
+		return CL_EWRITE;
248
+	    }
249
+	    break;
250
+	} else {
251
+	    if(cli_writen(newfd, buff, bread) == -1) {
252
+		cli_errmsg("cli_dumpscan: Can't write to %s\n", name);
253
+		cli_unlink(name);
254
+		free(name);
255
+		close(newfd);
256
+		return CL_EWRITE;
257
+	    }
258
+	}
259
+	sum += bread;
260
+	offset += bread;
261
+    }
262
+    cli_dbgmsg("SWF: %s data extracted to %s\n", obj, name);
263
+    lseek(newfd, 0, SEEK_SET);
264
+    if((ret = cli_magic_scandesc(newfd, ctx)) == CL_VIRUS)
265
+	cli_dbgmsg("cli_dumpscan: Infected with %s\n", *ctx->virname);
266
+
267
+    close(newfd);
268
+    if(!ctx->engine->keeptmp) {
269
+	if(cli_unlink(name)) {
270
+	    free(name);
271
+	    return CL_EUNLINK;
272
+	}
273
+    }
274
+    free(name);
275
+    return ret;
276
+}
277
+
224 278
 int cli_scanswf(cli_ctx *ctx)
225 279
 {
226 280
 	struct swf_file_hdr file_hdr;
227 281
 	int compressed = 0;
228 282
 	fmap_t *map = *ctx->fmap;
229 283
 	unsigned int bitpos, bitbuf, getbits_n, nbits, getword_1, getword_2, getdword_1, getdword_2;
284
+	const char *pt;
230 285
 	char get_c;
231
-	unsigned int fr, fps, foo, offset = 0, tag_hdr, tag_type, tag_len;
286
+	unsigned int val, fps, foo, offset = 0, tag_hdr, tag_type, tag_len;
232 287
 	unsigned long int bits;
233 288
 
234 289
 
... ...
@@ -262,8 +317,8 @@ int cli_scanswf(cli_ctx *ctx)
262 262
     GETBITS(foo, nbits); /* yMax */
263 263
 
264 264
     GETWORD(foo);
265
-    GETWORD(fr);
266
-    cli_dbgmsg("SWF: Frames total: %d\n", fr);
265
+    GETWORD(val);
266
+    cli_dbgmsg("SWF: Frames total: %d\n", val);
267 267
 
268 268
     while(offset < map->len) {
269 269
 	GETWORD(tag_hdr);
... ...
@@ -274,30 +329,15 @@ int cli_scanswf(cli_ctx *ctx)
274 274
 	if(tag_len == 0x3f)
275 275
 	    GETDWORD(tag_len);
276 276
 
277
-	cli_dbgmsg("SWF: %s\n", tagname(tag_type) ? tagname(tag_type) : "UNKNOWN TAG");
277
+	pt = tagname(tag_type);
278
+	cli_dbgmsg("SWF: %s\n", pt ? pt : "UNKNOWN TAG");
278 279
 	cli_dbgmsg("SWF: Tag length: %u\n", tag_len);
279
-	offset += tag_len;
280
-	continue;
280
+	if(!pt) {
281
+	    offset += tag_len;
282
+	    continue;
283
+	}
281 284
 
282 285
 	switch(tag_type) {
283
-	    case TAG_DOACTION:
284
-		break;
285
-
286
-	    case TAG_INITMOVIECLIP:
287
-		break;
288
-
289
-	    case TAG_PLACEOBJECT2:
290
-		break;
291
-
292
-	    case TAG_PLACEOBJECT3:
293
-		break;
294
-
295
-	    case TAG_DEFINEBUTTON2:
296
-		break;
297
-
298
-	    case TAG_SHOWFRAME:
299
-		break;
300
-
301 286
 	    case TAG_SCRIPTLIMITS: {
302 287
 		    unsigned int recursion, timeout;
303 288
 		GETWORD(recursion);
... ...
@@ -306,33 +346,52 @@ int cli_scanswf(cli_ctx *ctx)
306 306
 		break;
307 307
 	    }
308 308
 
309
-	    case TAG_PROTECT:
310
-		break;
311
-
312
-	    case TAG_ENABLEDEBUGGER:
313
-		break;
314
-
315
-	    case TAG_ENABLEDEBUGGER2:
316
-		break;
317
-
318
-	    case TAG_DEFINEMOVIECLIP:
319
-		break;
320
-
321
-	    case TAG_EXPORTASSETS:
309
+	    case TAG_METADATA:
322 310
 		break;
323 311
 
324
-	    case TAG_IMPORTASSETS:
325
-	    case TAG_IMPORTASSETS2:
312
+	    case TAG_FILEATTRIBUTES:
313
+		GETDWORD(val);
314
+		cli_dbgmsg("SWF: File attributes:\n");
315
+		if(val & SWF_ATTR_USENETWORK)
316
+		    cli_dbgmsg("    * Use network\n");
317
+		if(val & SWF_ATTR_RELATIVEURLS)
318
+		    cli_dbgmsg("    * Relative URLs\n");
319
+		if(val & SWF_ATTR_SUPPRESSCROSSDOMAINCACHE)
320
+		    cli_dbgmsg("    * Suppress cross domain cache\n");
321
+		if(val & SWF_ATTR_ACTIONSCRIPT3)
322
+		    cli_dbgmsg("    * ActionScript 3.0\n");
323
+		if(val & SWF_ATTR_HASMETADATA)
324
+		    cli_dbgmsg("    * Has metadata\n");
325
+		if(val & SWF_ATTR_USEDIRECTBLIT)
326
+		    cli_dbgmsg("    * Use hardware acceleration\n");
327
+		if(val & SWF_ATTR_USEGPU)
328
+		    cli_dbgmsg("    * Use GPU\n");
326 329
 		break;
327 330
 
328
-	    case TAG_METADATA:
331
+	    case TAG_DEFINEBITSJPEG3:
332
+		GETWORD(foo); /* CharacterID */
333
+		GETDWORD(val); /* AlphaDataOffset */
334
+		if(val) {
335
+		    if(dumpscan(map, offset, val, "Image", ctx) == CL_VIRUS)
336
+			return CL_VIRUS;
337
+		}
338
+		offset += tag_len - 6;
329 339
 		break;
330 340
 
331
-	    case TAG_FILEATTRIBUTES:
341
+	    case TAG_DEFINEBINARYDATA:
342
+		GETWORD(foo); /* CharacterID */
343
+		GETDWORD(foo); /* Reserved */
344
+		if(tag_len > 6) {
345
+		    if(dumpscan(map, offset, tag_len - 6, "Binary", ctx) == CL_VIRUS)
346
+			return CL_VIRUS;
347
+		}
348
+		offset += tag_len - 6;
332 349
 		break;
333 350
 
334 351
 	    default:
335
-		break;
352
+		cli_dbgmsg("SWF: Unhandled tag\n");
353
+		offset += tag_len;
354
+		continue;
336 355
 	}
337 356
     }
338 357
 
... ...
@@ -112,6 +112,7 @@ typedef enum
112 112
     TAG_AVM2ACTION		= 82,
113 113
     TAG_DEFINESHAPE5		= 83,
114 114
     TAG_DEFINEMORPHSHAPE2	= 84,
115
+    TAG_DEFINEBINARYDATA	= 87,
115 116
     TAG_DEFINEBITSPTR		= 1023,
116 117
     TAG_UNKNOWN			= 9999
117 118
 } tag_id;
... ...
@@ -194,8 +195,17 @@ static const struct tag_names_s {
194 194
     { "TAG_AVM2ACTION",			TAG_AVM2ACTION		},
195 195
     { "TAG_DEFINESHAPE5",		TAG_DEFINESHAPE5	},
196 196
     { "TAG_DEFINEMORPHSHAPE2",		TAG_DEFINEMORPHSHAPE2	},
197
+    { "TAG_DEFINEBINARYDATA",		TAG_DEFINEBINARYDATA	},
197 198
     { "TAG_DEFINEBITSPTR",		TAG_DEFINEBITSPTR	},
198 199
     { NULL,				TAG_UNKNOWN		},
199 200
 };
200 201
 
202
+#define SWF_ATTR_USENETWORK                 0x01
203
+#define SWF_ATTR_RELATIVEURLS               0x02
204
+#define SWF_ATTR_SUPPRESSCROSSDOMAINCACHE   0x04
205
+#define SWF_ATTR_ACTIONSCRIPT3              0x08
206
+#define SWF_ATTR_HASMETADATA                0x10
207
+#define SWF_ATTR_USEDIRECTBLIT		    0x20
208
+#define SWF_ATTR_USEGPU			    0x40
209
+
201 210
 #endif