Browse code

scanpe to fmap

aCaB authored on 2009/09/01 00:26:22
Showing 5 changed files
... ...
@@ -400,6 +400,20 @@ void fmap_unneed_ptr(struct F_MAP *m, void *ptr, size_t len) {
400 400
     return fmap_unneed_off(m, (char *)ptr - (char *)m - m->hdrsz, len);
401 401
 }
402 402
 
403
+int fmap_readn(struct F_MAP *m, void *dst, size_t at, size_t len) {
404
+    char *src;
405
+
406
+    if(at > m->len)
407
+	return -1;
408
+    if(len > m->len - at)
409
+	len = m->len - at;
410
+    src = fmap_need_off_once(m, at, len);
411
+    if(!src)
412
+	return -1;
413
+    memcpy(dst, src, len);
414
+    return len;
415
+}
416
+
403 417
 void fmunmap(struct F_MAP *m) {
404 418
     void *p = (void *)m;
405 419
     size_t len = m->pages * m->pgsz + m->hdrsz;
... ...
@@ -43,4 +43,5 @@ void *fmap_need_ptr(struct F_MAP *m, void *ptr, size_t len);
43 43
 void *fmap_need_ptr_once(struct F_MAP *m, void *ptr, size_t len);
44 44
 void fmap_unneed_off(struct F_MAP *m, size_t at, size_t len);
45 45
 void fmap_unneed_ptr(struct F_MAP *m, void *ptr, size_t len);
46
+int fmap_readn(struct F_MAP *m, void *dst, size_t at, size_t len);
46 47
 #endif
... ...
@@ -38,6 +38,7 @@
38 38
 #include "cltypes.h"
39 39
 #include "clamav.h"
40 40
 #include "others.h"
41
+#include "fmap.h"
41 42
 #include "pe.h"
42 43
 #include "petite.h"
43 44
 #include "fsg.h"
... ...
@@ -290,7 +291,7 @@ static off_t cli_seeksect(int fd, struct cli_exe_section *s) {
290 290
     return ret+1;
291 291
 }
292 292
 
293
-static unsigned int cli_md5sect(int fd, struct cli_exe_section *s, unsigned char *digest) {
293
+static unsigned int cli_md5sect(struct F_MAP *map, struct cli_exe_section *s, unsigned char *digest) {
294 294
     void *hashme;
295 295
     cli_md5_ctx md5;
296 296
 
... ...
@@ -299,28 +300,21 @@ static unsigned int cli_md5sect(int fd, struct cli_exe_section *s, unsigned char
299 299
 	return 0;
300 300
     }
301 301
 
302
-    if(!cli_seeksect(fd, s)) return 0;
303
-
304
-    if(!(hashme=cli_malloc(s->rsz))) {
305
-	cli_dbgmsg("cli_md5sect: out of memory\n");
306
-	return 0;
307
-    }
308
-
309
-    if(cli_readn(fd, hashme, s->rsz)!=s->rsz) {
302
+    if(!s->rsz) return 0;
303
+    if(!(hashme=fmap_need_off_once(map, s->raw, s->rsz))) {
310 304
 	cli_dbgmsg("cli_md5sect: unable to read section data\n");
311 305
 	return 0;
312 306
     }
313 307
 
314 308
     cli_md5_init(&md5);
315 309
     cli_md5_update(&md5, hashme, s->rsz);
316
-    free(hashme);
317 310
     cli_md5_final(digest, &md5);
318 311
     return 1;
319 312
 }
320 313
 
321
-static void cli_parseres_special(uint32_t base, uint32_t rva, int srcfd, struct cli_exe_section *exe_sections, uint16_t nsections, size_t fsize, uint32_t hdr_size, unsigned int level, uint32_t type, unsigned int *maxres, struct swizz_stats *stats) {
314
+static void cli_parseres_special(uint32_t base, uint32_t rva, struct F_MAP *map, struct cli_exe_section *exe_sections, uint16_t nsections, size_t fsize, uint32_t hdr_size, unsigned int level, uint32_t type, unsigned int *maxres, struct swizz_stats *stats) {
322 315
     unsigned int err = 0, i;
323
-    uint8_t resdir[16];
316
+    uint8_t *resdir;
324 317
     uint8_t *entry, *oentry;
325 318
     uint16_t named, unnamed;
326 319
     uint32_t rawaddr = cli_rawaddr(rva, exe_sections, nsections, &err, fsize, hdr_size);
... ...
@@ -328,7 +322,7 @@ static void cli_parseres_special(uint32_t base, uint32_t rva, int srcfd, struct
328 328
 
329 329
     if(level>2 || !*maxres) return;
330 330
     *maxres-=1;
331
-    if(err || (pread(srcfd,resdir, sizeof(resdir), rawaddr) != sizeof(resdir)))
331
+    if(err || !(resdir = fmap_need_off_once(map, rawaddr, 16)))
332 332
 	    return;
333 333
     named = (uint16_t)cli_readint16(resdir+12);
334 334
     unnamed = (uint16_t)cli_readint16(resdir+14);
... ...
@@ -336,18 +330,17 @@ static void cli_parseres_special(uint32_t base, uint32_t rva, int srcfd, struct
336 336
     entries = /*named+*/unnamed;
337 337
     if (!entries)
338 338
 	    return;
339
-    oentry = entry = cli_malloc(entries*8);
340 339
     rawaddr += named*8; /* skip named */
341 340
     /* this is just used in a heuristic detection, so don't give error on failure */
342 341
     if (!entry) {
343 342
 	    cli_dbgmsg("cli_parseres_special: failed to allocate memory for resource directory:%lu\n", (unsigned long)entries);
344 343
 	    return;
345 344
     }
346
-    if (pread(srcfd, entry, entries*8, rawaddr+16) != entries*8) {
345
+    if(!(entry = fmap_need_off(map, rawaddr+16, entries*8))) {
347 346
 	    cli_dbgmsg("cli_parseres_special: failed to read resource directory at:%lu\n", (unsigned long)rawaddr+16);
348
-	    free(oentry);
349 347
 	    return;
350 348
     }
349
+    oentry = entry;
351 350
     /*for (i=0; i<named; i++) {
352 351
 	uint32_t id, offs;
353 352
 	id = cli_readint32(entry);
... ...
@@ -389,13 +382,13 @@ static void cli_parseres_special(uint32_t base, uint32_t rva, int srcfd, struct
389 389
 	}
390 390
 	offs = cli_readint32(entry+4);
391 391
 	if(offs>>31)
392
-		cli_parseres_special(base, base + (offs&0x7fffffff), srcfd, exe_sections, nsections, fsize, hdr_size, level+1, type, maxres, stats);
392
+		cli_parseres_special(base, base + (offs&0x7fffffff), map, exe_sections, nsections, fsize, hdr_size, level+1, type, maxres, stats);
393 393
 	else {
394 394
 			offs = cli_readint32(entry+4);
395 395
 			rawaddr = cli_rawaddr(base + offs, exe_sections, nsections, &err, fsize, hdr_size);
396
-			if (!err && pread(srcfd, resdir, sizeof(resdir), rawaddr) == sizeof(resdir)) {
396
+			if (!err && (resdir = fmap_need_off_once(map, rawaddr, 16))) {
397 397
 				uint32_t isz = cli_readint32(resdir+4);
398
-				char *str;
398
+				uint8_t *str;
399 399
 				rawaddr = cli_rawaddr(cli_readint32(resdir), exe_sections, nsections, &err, fsize, hdr_size);
400 400
 				if (err || !isz || isz >= fsize || rawaddr+isz >= fsize) {
401 401
 					cli_dbgmsg("cli_parseres_special: invalid resource table entry: %lu + %lu\n", 
... ...
@@ -404,22 +397,15 @@ static void cli_parseres_special(uint32_t base, uint32_t rva, int srcfd, struct
404 404
 					stats->errors++;
405 405
 					continue;
406 406
 				}
407
-				str = cli_malloc(isz);
408
-				if (!str) {
409
-					cli_dbgmsg("cli_parseres_special: failed to allocate string mem: %lu\n", (unsigned long)isz);
410
-					continue;
411
-				}
412
-				if(pread(srcfd, str, isz, rawaddr) == isz) {
407
+				if((str = fmap_need_off_once(map, rawaddr, isz)))
413 408
 					cli_detect_swizz_str(str, isz, stats, type);
414
-				}
415
-				free (str);
416 409
 			}
417 410
 	}
418 411
     }
419
-    free (oentry);
412
+    fmap_unneed_ptr(map, oentry, entries*8);
420 413
 }
421 414
 
422
-int cli_scanpe(int desc, cli_ctx *ctx)
415
+int cli_scanpe(cli_ctx *ctx)
423 416
 {
424 417
 	uint16_t e_magic; /* DOS signature ("MZ") */
425 418
 	uint16_t nsections;
... ...
@@ -433,10 +419,9 @@ int cli_scanpe(int desc, cli_ctx *ctx)
433 433
 	    struct pe_image_optional_hdr32 opt32;
434 434
 	} pe_opt;
435 435
 	struct pe_image_section_hdr *section_hdr;
436
-	struct stat sb;
437
-	char sname[9], buff[4096], epbuff[4096], *tempfile;
436
+	char sname[9], epbuff[4096], *tempfile;
438 437
 	uint32_t epsize;
439
-	ssize_t bytes;
438
+	ssize_t bytes, at;
440 439
 	unsigned int i, found, upx_success = 0, min = 0, max = 0, err, overlays = 0;
441 440
 	unsigned int ssize = 0, dsize = 0, dll = 0, pe_plus = 0;
442 441
 	int (*upxfn)(char *, uint32_t, char *, uint32_t *, uint32_t, uint32_t, uint32_t) = NULL;
... ...
@@ -448,6 +433,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
448 448
 	struct cli_matcher *md5_sect;
449 449
 	char timestr[32];
450 450
 	struct pe_image_data_dir *dirs;
451
+	struct F_MAP *map;
451 452
 
452 453
 
453 454
     if(!ctx) {
... ...
@@ -455,7 +441,8 @@ int cli_scanpe(int desc, cli_ctx *ctx)
455 455
 	return CL_ENULLARG;
456 456
     }
457 457
 
458
-    if(cli_readn(desc, &e_magic, sizeof(e_magic)) != sizeof(e_magic)) {
458
+    map = *ctx->fmap;
459
+    if(fmap_readn(map, &e_magic, 0, sizeof(e_magic)) != sizeof(e_magic)) {
459 460
 	cli_dbgmsg("Can't read DOS signature\n");
460 461
 	return CL_CLEAN;
461 462
     }
... ...
@@ -465,15 +452,13 @@ int cli_scanpe(int desc, cli_ctx *ctx)
465 465
 	return CL_CLEAN;
466 466
     }
467 467
 
468
-    lseek(desc, 58, SEEK_CUR); /* skip to the end of the DOS header */
469
-
470
-    if(cli_readn(desc, &e_lfanew, sizeof(e_lfanew)) != sizeof(e_lfanew)) {
468
+    if(fmap_readn(map, &e_lfanew, 58 + sizeof(e_magic), sizeof(e_lfanew)) != sizeof(e_lfanew)) {
471 469
 	cli_dbgmsg("Can't read new header address\n");
472 470
 	/* truncated header? */
473 471
 	if(DETECT_BROKEN) {
474 472
 	    if(ctx->virname)
475 473
 		*ctx->virname = "Broken.Executable";
476
-	    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
474
+	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
477 475
 	}
478 476
 	return CL_CLEAN;
479 477
     }
... ...
@@ -485,13 +470,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
485 485
 	return CL_CLEAN;
486 486
     }
487 487
 
488
-    if(lseek(desc, e_lfanew, SEEK_SET) < 0) {
489
-	/* probably not a PE file */
490
-	cli_dbgmsg("Can't lseek to e_lfanew\n");
491
-	return CL_CLEAN;
492
-    }
493
-
494
-    if(cli_readn(desc, &file_hdr, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) {
488
+    if(fmap_readn(map, &file_hdr, e_lfanew, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) {
495 489
 	/* bad information in e_lfanew - probably not a PE file */
496 490
 	cli_dbgmsg("Can't read file header\n");
497 491
 	return CL_CLEAN;
... ...
@@ -609,7 +588,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
609 609
 	if(DETECT_BROKEN) {
610 610
 	    if(ctx->virname)
611 611
 		*ctx->virname = "Broken.Executable";
612
-	    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
612
+	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
613 613
 	}
614 614
 	if(nsections)
615 615
 	    cli_warnmsg("PE file contains %d sections\n", nsections);
... ...
@@ -629,20 +608,22 @@ int cli_scanpe(int desc, cli_ctx *ctx)
629 629
 	if(DETECT_BROKEN) {
630 630
 	    if(ctx->virname)
631 631
 	        *ctx->virname = "Broken.Executable";
632
-	    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
632
+	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
633 633
 	}
634 634
 	return CL_CLEAN;
635 635
     }
636 636
 
637
-    if(cli_readn(desc, &optional_hdr32, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) {
637
+    at = e_lfanew + sizeof(struct pe_image_file_hdr);
638
+    if(fmap_readn(map, &optional_hdr32, at, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) {
638 639
         cli_dbgmsg("Can't read optional file header\n");
639 640
 	if(DETECT_BROKEN) {
640 641
 	    if(ctx->virname)
641 642
 	        *ctx->virname = "Broken.Executable";
642
-	    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
643
+	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
643 644
 	}
644 645
 	return CL_CLEAN;
645 646
     }
647
+    at += sizeof(struct pe_image_optional_hdr32);
646 648
 
647 649
     /* This will be a chicken and egg problem until we drop 9x */
648 650
     if(EC16(optional_hdr64.Magic)==PE32P_SIGNATURE) {
... ...
@@ -652,7 +633,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
652 652
 	    if(DETECT_BROKEN) {
653 653
 	        if(ctx->virname)
654 654
 		    *ctx->virname = "Broken.Executable";
655
-		return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
655
+		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
656 656
 	    }
657 657
 	    return CL_CLEAN;
658 658
 	}
... ...
@@ -668,7 +649,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
668 668
 	    if(DETECT_BROKEN) {
669 669
 	        if(ctx->virname)
670 670
 		    *ctx->virname = "Broken.Executable";
671
-		return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
671
+		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
672 672
 	    }
673 673
 	    cli_dbgmsg("9x compatibility mode\n");
674 674
 	}
... ...
@@ -677,7 +658,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
677 677
     if(!pe_plus) { /* PE */
678 678
 	if (EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr32)) {
679 679
 	    /* Seek to the end of the long header */
680
-	    lseek(desc, (EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32)), SEEK_CUR);
680
+	    at += EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32);
681 681
 	}
682 682
 
683 683
 	if(DCONF & PE_CONF_UPACK)
... ...
@@ -705,16 +686,16 @@ int cli_scanpe(int desc, cli_ctx *ctx)
705 705
 
706 706
     } else { /* PE+ */
707 707
         /* read the remaining part of the header */
708
-        if(cli_readn(desc, &optional_hdr32 + 1, sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) {
708
+        if(fmap_readn(map, &optional_hdr32 + 1, at, sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) {
709 709
 	    cli_dbgmsg("Can't read optional file header\n");
710 710
 	    if(DETECT_BROKEN) {
711 711
 	        if(ctx->virname)
712 712
 		    *ctx->virname = "Broken.Executable";
713
-		return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
713
+		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
714 714
 	    }
715 715
 	    return CL_CLEAN;
716 716
 	}
717
-
717
+	at += sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32);
718 718
 	vep = EC32(optional_hdr64.AddressOfEntryPoint);
719 719
 	hdr_size = EC32(optional_hdr64.SizeOfHeaders);
720 720
 	cli_dbgmsg("File format: PE32+\n");
... ...
@@ -791,22 +772,17 @@ int cli_scanpe(int desc, cli_ctx *ctx)
791 791
         cli_dbgmsg("Bad virtual alignemnt\n");
792 792
         if(ctx->virname)
793 793
 	    *ctx->virname = "Broken.Executable";
794
-	return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
794
+	return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
795 795
     }
796 796
 
797 797
     if (DETECT_BROKEN && !native && (!(pe_plus?EC32(optional_hdr64.FileAlignment):EC32(optional_hdr32.FileAlignment)) || (pe_plus?EC32(optional_hdr64.FileAlignment):EC32(optional_hdr32.FileAlignment))%0x200)) {
798 798
         cli_dbgmsg("Bad file alignemnt\n");
799 799
 	if(ctx->virname)
800 800
 	    *ctx->virname = "Broken.Executable";
801
-	return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
801
+	return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
802 802
     }
803 803
 
804
-    if(fstat(desc, &sb) == -1) {
805
-	cli_dbgmsg("fstat failed\n");
806
-	return CL_ESTAT;
807
-    }
808
-
809
-    fsize = sb.st_size;
804
+    fsize = map->len;
810 805
 
811 806
     section_hdr = (struct pe_image_section_hdr *) cli_calloc(nsections, sizeof(struct pe_image_section_hdr));
812 807
 
... ...
@@ -826,7 +802,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
826 826
     valign = (pe_plus)?EC32(optional_hdr64.SectionAlignment):EC32(optional_hdr32.SectionAlignment);
827 827
     falign = (pe_plus)?EC32(optional_hdr64.FileAlignment):EC32(optional_hdr32.FileAlignment);
828 828
 
829
-    if(cli_readn(desc, section_hdr, sizeof(struct pe_image_section_hdr)*nsections) != (int)(nsections*sizeof(struct pe_image_section_hdr))) {
829
+    if(fmap_readn(map, section_hdr, at, sizeof(struct pe_image_section_hdr)*nsections) != (int)(nsections*sizeof(struct pe_image_section_hdr))) {
830 830
         cli_dbgmsg("Can't read section header\n");
831 831
 	cli_dbgmsg("Possibly broken PE file\n");
832 832
 	free(section_hdr);
... ...
@@ -834,11 +810,12 @@ int cli_scanpe(int desc, cli_ctx *ctx)
834 834
 	if(DETECT_BROKEN) {
835 835
 	    if(ctx->virname)
836 836
 		*ctx->virname = "Broken.Executable";
837
-	    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
837
+	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
838 838
 	}
839 839
 	return CL_CLEAN;
840 840
     }
841
-    
841
+    at += sizeof(struct pe_image_section_hdr)*nsections;
842
+
842 843
     for(i = 0; falign!=0x200 && i<nsections; i++) {
843 844
 	/* file alignment fallback mode - blah */
844 845
 	if (falign && section_hdr[i].SizeOfRawData && EC32(section_hdr[i].PointerToRawData)%falign && !(EC32(section_hdr[i].PointerToRawData)%0x200)) {
... ...
@@ -903,7 +880,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
903 903
 	        *ctx->virname = "Broken.Executable";
904 904
 	    free(section_hdr);
905 905
 	    free(exe_sections);
906
-	    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
906
+	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
907 907
 	}
908 908
 
909 909
 	if (exe_sections[i].rsz) { /* Don't bother with virtual only sections */
... ...
@@ -914,7 +891,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
914 914
 		if(DETECT_BROKEN) {
915 915
 		    if(ctx->virname)
916 916
 		        *ctx->virname = "Broken.Executable";
917
-		    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
917
+		    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
918 918
 		}
919 919
 		return CL_CLEAN; /* no ninjas to see here! move along! */
920 920
 	    }
... ...
@@ -928,12 +905,12 @@ int cli_scanpe(int desc, cli_ctx *ctx)
928 928
 		for(j = 0; j < md5_sect->soff_len && md5_sect->soff[j] <= exe_sections[i].rsz; j++) {
929 929
 		    if(md5_sect->soff[j] == exe_sections[i].rsz) {
930 930
 			unsigned char md5_dig[16];
931
-			if(cli_md5sect(desc, &exe_sections[i], md5_dig) && cli_bm_scanbuff(md5_dig, 16, ctx->virname, ctx->engine->md5_mdb, 0, -1) == CL_VIRUS) {
931
+			if(cli_md5sect(map, &exe_sections[i], md5_dig) && cli_bm_scanbuff(md5_dig, 16, ctx->virname, ctx->engine->md5_mdb, 0, -1) == CL_VIRUS) {
932 932
 			    if(cli_bm_scanbuff(md5_dig, 16, NULL, ctx->engine->md5_fp, 0, -1) != CL_VIRUS) {
933 933
 
934 934
 				free(section_hdr);
935 935
 				free(exe_sections);
936
-				return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
936
+				return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
937 937
 			    }
938 938
 			}
939 939
 			break;
... ...
@@ -949,7 +926,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
949 949
 	    if(DETECT_BROKEN) {
950 950
 	        if(ctx->virname)
951 951
 		    *ctx->virname = "Broken.Executable";
952
-		return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
952
+		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
953 953
 	    }
954 954
 	    return CL_CLEAN;
955 955
 	}
... ...
@@ -961,7 +938,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
961 961
 		    *ctx->virname = "Broken.Executable";
962 962
 		free(section_hdr);
963 963
 		free(exe_sections);
964
-		return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
964
+		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
965 965
 	    }
966 966
 	    min = exe_sections[i].rva;
967 967
 	    max = exe_sections[i].rva + exe_sections[i].rsz;
... ...
@@ -972,7 +949,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
972 972
 		    *ctx->virname = "Broken.Executable";
973 973
 		free(section_hdr);
974 974
 		free(exe_sections);
975
-		return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
975
+		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
976 976
 	    }
977 977
 	    if(exe_sections[i].rva < min)
978 978
 	        min = exe_sections[i].rva;
... ...
@@ -992,7 +969,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
992 992
 	if(DETECT_BROKEN) {
993 993
 	    if(ctx->virname)
994 994
 		*ctx->virname = "Broken.Executable";
995
-	    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
995
+	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
996 996
 	}
997 997
 	return CL_CLEAN;
998 998
     }
... ...
@@ -1004,8 +981,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1004 1004
 	return CL_CLEAN;
1005 1005
     }
1006 1006
 
1007
-    lseek(desc, ep, SEEK_SET);
1008
-    epsize = cli_readn(desc, epbuff, 4096);
1007
+    epsize = fmap_readn(map, epbuff, ep, 4096);
1009 1008
 
1010 1009
     CLI_UNPTEMP("DISASM",(exe_sections,0));
1011 1010
     disasmbuf((unsigned char*)epbuff, epsize, ndesc);
... ...
@@ -1022,7 +998,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1022 1022
     if(overlays) {
1023 1023
 	int overlays_sz = fsize - overlays;
1024 1024
 	if(overlays_sz > 0) {
1025
-	    ret = cli_scanishield(desc, ctx, overlays, overlays_sz);
1025
+	    ret = cli_scanishield(map->fd, ctx, overlays, overlays_sz);
1026 1026
 	    if(ret != CL_CLEAN) {
1027 1027
 		free(exe_sections);
1028 1028
 		return ret;
... ...
@@ -1040,7 +1016,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1040 1040
 	    if((((uint32_t)cli_readint32(pt) ^ (uint32_t)cli_readint32(pt + 4)) == 0x505a4f) && (((uint32_t)cli_readint32(pt + 8) ^ (uint32_t)cli_readint32(pt + 12)) == 0xffffb) && (((uint32_t)cli_readint32(pt + 16) ^ (uint32_t)cli_readint32(pt + 20)) == 0xb8)) {
1041 1041
 	        *ctx->virname = "W32.Parite.B";
1042 1042
 		free(exe_sections);
1043
-		return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
1043
+		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
1044 1044
 	    }
1045 1045
 	}
1046 1046
     }
... ...
@@ -1123,7 +1099,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1123 1123
 		if (op==kzdsize+0x48 && *kzcode==0x75 && kzlen-(int8_t)kzcode[1]-3<=kzinitlen && kzlen-(int8_t)kzcode[1]>=kzxorlen) {
1124 1124
 		    *ctx->virname = "W32.Kriz";
1125 1125
 		    free(exe_sections);
1126
-		    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
1126
+		    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
1127 1127
 		}
1128 1128
 		cli_dbgmsg("kriz: loop out of bounds, corrupted sample?\n");
1129 1129
 		kzstate++;
... ...
@@ -1144,25 +1120,25 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1144 1144
 
1145 1145
 	if(vsize >= 0x612c && rsize >= 0x612c && ((vsize & 0xff) == 0xec)) {
1146 1146
 		int bw = rsize < 0x7000 ? rsize : 0x7000;
1147
+		char *tbuff;
1147 1148
 
1148
-	    lseek(desc, exe_sections[nsections - 1].raw + rsize - bw, SEEK_SET);
1149
-	    if(cli_readn(desc, buff, 4096) == 4096) {
1150
-		if(cli_memstr(buff, 4091, "\xe8\x2c\x61\x00\x00", 5)) {
1149
+	    if((tbuff = fmap_need_off_once(map, exe_sections[nsections - 1].raw + rsize - bw, 4096))) {
1150
+		if(cli_memstr(tbuff, 4091, "\xe8\x2c\x61\x00\x00", 5)) {
1151 1151
 		    *ctx->virname = dam ? "W32.Magistr.A.dam" : "W32.Magistr.A";
1152 1152
 		    free(exe_sections);
1153
-		    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
1153
+		    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
1154 1154
 		} 
1155 1155
 	    }
1156 1156
 
1157 1157
 	} else if(rsize >= 0x7000 && vsize >= 0x7000 && ((vsize & 0xff) == 0xed)) {
1158 1158
 		int bw = rsize < 0x8000 ? rsize : 0x8000;
1159
+		char *tbuff;
1159 1160
 
1160
-	    lseek(desc, exe_sections[nsections - 1].raw + rsize - bw, SEEK_SET);
1161
-	    if(cli_readn(desc, buff, 4096) == 4096) {
1162
-		if(cli_memstr(buff, 4091, "\xe8\x04\x72\x00\x00", 5)) {
1161
+	    if((tbuff = fmap_need_off_once(map, exe_sections[nsections - 1].raw + rsize - bw, 4096))) {
1162
+		if(cli_memstr(tbuff, 4091, "\xe8\x04\x72\x00\x00", 5)) {
1163 1163
 		    *ctx->virname = dam ? "W32.Magistr.B.dam" : "W32.Magistr.B";
1164 1164
 		    free(exe_sections);
1165
-		    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
1165
+		    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
1166 1166
 		} 
1167 1167
 	    }
1168 1168
 	}
... ...
@@ -1175,15 +1151,9 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1175 1175
 	unsigned int xsjs = 0;
1176 1176
 
1177 1177
 	if(exe_sections[0].rsz > CLI_MAX_ALLOCATION) break;
1178
-	if(!cli_seeksect(desc, &exe_sections[0])) break;
1179
-	if(!(code=cli_malloc(exe_sections[0].rsz))) {
1180
-	    free(exe_sections);
1181
-	    return CL_EMEM;
1182
-	}
1183
-	if(cli_readn(desc, code, exe_sections[0].rsz)!=exe_sections[0].rsz) {
1184
-	    free(exe_sections);
1185
-	    return CL_EREAD;
1186
-	}
1178
+
1179
+	if(!exe_sections[0].rsz) break;
1180
+	if(!(code=fmap_need_off_once(map, exe_sections[0].raw, exe_sections[0].rsz))) break;
1187 1181
 	for(i=0; i<exe_sections[0].rsz - 5; i++) {
1188 1182
 	    if((uint8_t)(code[i]-0xe8) > 1) continue;
1189 1183
 	    jump = cli_rawaddr(exe_sections[0].rva+i+5+cli_readint32(&code[i+1]), exe_sections, nsections, &err, fsize, hdr_size);
... ...
@@ -1191,7 +1161,6 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1191 1191
 	    if(xsjs % 128 == 0) {
1192 1192
 		if(xsjs == 1280) break;
1193 1193
 		if(!(jumps=(uint32_t *)cli_realloc2(jumps, (xsjs+128)*sizeof(uint32_t)))) {
1194
-		    free(code);
1195 1194
 		    free(exe_sections);
1196 1195
 		    return CL_EMEM;
1197 1196
 		}
... ...
@@ -1210,17 +1179,15 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1210 1210
 	    jumps[j]=jump;
1211 1211
 	    xsjs++;
1212 1212
 	}
1213
-	free(code);
1214 1213
 	if(!xsjs) break;
1215 1214
 	cli_dbgmsg("Polipos: Checking %d xsect jump(s)\n", xsjs);
1216 1215
 	for(i=0;i<xsjs;i++) {
1217
-	    lseek(desc, jumps[i], SEEK_SET);
1218
-	    if(cli_readn(desc, buff, 9) != 9) continue;
1219
-	    if((jump=cli_readint32(buff))==0x60ec8b55 || (buff[4]=='\xec' && ((jump==0x83ec8b55 && buff[6]=='\x60') || (jump==0x81ec8b55 && !buff[7] && !buff[8])))) {
1216
+	    if(!(code = fmap_need_off_once(map, jumps[i], 9))) continue;
1217
+	    if((jump=cli_readint32(code))==0x60ec8b55 || (code[4]=='\xec' && ((jump==0x83ec8b55 && code[6]=='\x60') || (jump==0x81ec8b55 && !code[7] && !code[8])))) {
1220 1218
 		*ctx->virname = "W32.Polipos.A";
1221 1219
 		free(jumps);
1222 1220
 		free(exe_sections);
1223
-		return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
1221
+		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
1224 1222
 	    }
1225 1223
 	}
1226 1224
 	free(jumps);
... ...
@@ -1237,7 +1204,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1237 1237
 		    if (!stats)
1238 1238
 			    ret = CL_EMEM;
1239 1239
 		    else {
1240
-			    cli_parseres_special(EC32(dirs[2].VirtualAddress), EC32(dirs[2].VirtualAddress), desc, exe_sections, nsections, fsize, hdr_size, 0, 0, &m, stats);
1240
+			    cli_parseres_special(EC32(dirs[2].VirtualAddress), EC32(dirs[2].VirtualAddress), map, exe_sections, nsections, fsize, hdr_size, 0, 0, &m, stats);
1241 1241
 			    if ((ret = cli_detect_swizz(stats)) == CL_VIRUS) {
1242 1242
 				    *ctx->virname = "Trojan.Swizzor.Gen";
1243 1243
 			    }
... ...
@@ -1246,7 +1213,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1246 1246
 		    if (ret != CL_CLEAN) {
1247 1247
 			    free(exe_sections);
1248 1248
 			    if(ret == CL_VIRUS)
1249
-				return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
1249
+				return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
1250 1250
 			    return ret;
1251 1251
 		    }
1252 1252
 	    }
... ...
@@ -1269,6 +1236,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1269 1269
     /* MEW support */
1270 1270
     if (found && (DCONF & PE_CONF_MEW) && epsize>=16 && epbuff[0]=='\xe9') {
1271 1271
 	uint32_t fileoffset;
1272
+	char *tbuff;
1272 1273
 
1273 1274
 	fileoffset = (vep + cli_readint32(epbuff + 1) + 5);
1274 1275
 	while (fileoffset == 0x154 || fileoffset == 0x158) {
... ...
@@ -1277,29 +1245,20 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1277 1277
 	    cli_dbgmsg ("MEW: found MEW characteristics %08X + %08X + 5 = %08X\n", 
1278 1278
 			cli_readint32(epbuff + 1), vep, cli_readint32(epbuff + 1) + vep + 5);
1279 1279
 
1280
-	    if(lseek(desc, fileoffset, SEEK_SET) == -1) {
1281
-	        cli_dbgmsg("MEW: lseek() failed\n");
1282
-		free(exe_sections);
1283
-		return CL_ESEEK;
1284
-	    }
1285
-
1286
-	    if((bytes = read(desc, buff, 0xb0)) != 0xb0) {
1287
-	        cli_dbgmsg("MEW: Can't read 0xb0 bytes at 0x%x (%d) %lu\n", fileoffset, fileoffset, (unsigned long)bytes);
1280
+	    if(!(tbuff = fmap_need_off_once(map, fileoffset, 0xb0)))
1288 1281
 		break;
1289
-	    }
1290
-
1291 1282
 	    if (fileoffset == 0x154) cli_dbgmsg("MEW: Win9x compatibility was set!\n");
1292 1283
 	    else cli_dbgmsg("MEW: Win9x compatibility was NOT set!\n");
1293 1284
 
1294
-	    if((offdiff = cli_readint32(buff+1) - EC32(optional_hdr32.ImageBase)) <= exe_sections[i + 1].rva || offdiff >= exe_sections[i + 1].rva + exe_sections[i + 1].raw - 4) {
1285
+	    if((offdiff = cli_readint32(tbuff+1) - EC32(optional_hdr32.ImageBase)) <= exe_sections[i + 1].rva || offdiff >= exe_sections[i + 1].rva + exe_sections[i + 1].raw - 4) {
1295 1286
 	        cli_dbgmsg("MEW: ESI is not in proper section\n");
1296 1287
 		break;
1297 1288
 	    }
1298 1289
 	    offdiff -= exe_sections[i + 1].rva;
1299 1290
 
1300
-	    if(!cli_seeksect(desc, &exe_sections[i + 1])) {
1301
-		free(exe_sections);
1302
-		return CL_ESEEK;
1291
+	    if(!exe_sections[i + 1].rsz) {
1292
+		cli_dbgmsg("MEW: mew section is empty\n");
1293
+		break;
1303 1294
 	    }
1304 1295
 	    ssize = exe_sections[i + 1].vsz;
1305 1296
 	    dsize = exe_sections[i].vsz;
... ...
@@ -1309,20 +1268,19 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1309 1309
 	    CLI_UNPSIZELIMITS("MEW", MAX(ssize, dsize));
1310 1310
 	    CLI_UNPSIZELIMITS("MEW", MAX(ssize + dsize, exe_sections[i + 1].rsz));
1311 1311
 
1312
+	    if (exe_sections[i + 1].rsz < offdiff + 12 || exe_sections[i + 1].rsz > ssize) {
1313
+	        cli_dbgmsg("MEW: Size mismatch: %08x\n", exe_sections[i + 1].rsz);
1314
+		break;
1315
+	    }
1316
+
1312 1317
 	    /* allocate needed buffer */
1313 1318
 	    if (!(src = cli_calloc (ssize + dsize, sizeof(char)))) {
1314 1319
 	        free(exe_sections);
1315 1320
 		return CL_EMEM;
1316 1321
 	    }
1317 1322
 
1318
-	    if (exe_sections[i + 1].rsz < offdiff + 12 || exe_sections[i + 1].rsz > ssize) {
1319
-	        cli_dbgmsg("MEW: Size mismatch: %08x\n", exe_sections[i + 1].rsz);
1320
-		free(src);
1321
-		break;
1322
-	    }
1323
-
1324
-	    if((bytes = read(desc, src + dsize, exe_sections[i + 1].rsz)) != exe_sections[i + 1].rsz) {
1325
-	      cli_dbgmsg("MEW: Can't read %d bytes [read: %lu]\n", exe_sections[i + 1].rsz, (unsigned long)bytes);
1323
+	    if((bytes = fmap_readn(map, src + dsize, exe_sections[i + 1].raw, exe_sections[i + 1].rsz)) != exe_sections[i + 1].rsz) {
1324
+		cli_dbgmsg("MEW: Can't read %d bytes [read: %lu]\n", exe_sections[i + 1].rsz, (unsigned long)bytes);
1326 1325
 		free(exe_sections);
1327 1326
 		free(src);
1328 1327
 		return CL_EREAD;
... ...
@@ -1330,13 +1288,13 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1330 1330
 	    cli_dbgmsg("MEW: %u (%08x) bytes read\n", (unsigned int)bytes, (unsigned int)bytes);
1331 1331
 
1332 1332
 	    /* count offset to lzma proc, if lzma used, 0xe8 -> call */
1333
-	    if (buff[0x7b] == '\xe8') {
1334
-	        if (!CLI_ISCONTAINED(exe_sections[1].rva, exe_sections[1].vsz, cli_readint32(buff + 0x7c) + fileoffset + 0x80, 4)) {
1333
+	    if (tbuff[0x7b] == '\xe8') {
1334
+	        if (!CLI_ISCONTAINED(exe_sections[1].rva, exe_sections[1].vsz, cli_readint32(tbuff + 0x7c) + fileoffset + 0x80, 4)) {
1335 1335
 		    cli_dbgmsg("MEW: lzma proc out of bounds!\n");
1336 1336
 		    free(src);
1337 1337
 		    break; /* to next unpacker in chain */
1338 1338
 		}
1339
-		uselzma = cli_readint32(buff + 0x7c) - (exe_sections[0].rva - fileoffset - 0x80);
1339
+		uselzma = cli_readint32(tbuff + 0x7c) - (exe_sections[0].rva - fileoffset - 0x80);
1340 1340
 	    } else {
1341 1341
 	        uselzma = 0;
1342 1342
 	    }
... ...
@@ -1433,8 +1391,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1433 1433
 		return CL_EMEM;
1434 1434
 	    }
1435 1435
 
1436
-	    lseek(desc, 0, SEEK_SET);
1437
-	    if(read(desc, dest, ssize) != ssize) {
1436
+	    if(fmap_readn(map, dest, 0, ssize) != ssize) {
1438 1437
 	        cli_dbgmsg("Upack: Can't read raw data of section 0\n");
1439 1438
 		free(dest);
1440 1439
 		break;
... ...
@@ -1442,9 +1399,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1442 1442
 
1443 1443
 	    if(upack) memmove(dest + exe_sections[2].rva - exe_sections[0].rva, dest, ssize);
1444 1444
 
1445
-	    lseek(desc, exe_sections[1].uraw, SEEK_SET);
1446
-
1447
-	    if(read(desc, dest + exe_sections[1].rva - off, exe_sections[1].ursz) != exe_sections[1].ursz) {
1445
+	    if(fmap_readn(map, dest + exe_sections[1].rva - off, exe_sections[1].uraw, exe_sections[1].ursz) != exe_sections[1].ursz) {
1448 1446
 		cli_dbgmsg("Upack: Can't read raw data of section 1\n");
1449 1447
 		free(dest);
1450 1448
 		break;
... ...
@@ -1485,31 +1440,27 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1485 1485
 	    return CL_EMEM;
1486 1486
 	}
1487 1487
 
1488
-	if(!cli_seeksect(desc, &exe_sections[i + 1]) || (unsigned int) cli_readn(desc, src, ssize) != ssize) {
1488
+	if(!exe_sections[i + 1].rsz || !(src = fmap_need_off_once(map, exe_sections[i + 1].raw, ssize))) {
1489 1489
 	    cli_dbgmsg("Can't read raw data of section %d\n", i + 1);
1490 1490
 	    free(exe_sections);
1491
-	    free(src);
1492 1491
 	    return CL_ESEEK;
1493 1492
 	}
1494 1493
 
1495 1494
 	dest = src + newedx - exe_sections[i + 1].rva;
1496 1495
 	if(newedx < exe_sections[i + 1].rva || !CLI_ISCONTAINED(src, ssize, dest, 4)) {
1497 1496
 	    cli_dbgmsg("FSG: New ESP out of bounds\n");
1498
-	    free(src);
1499 1497
 	    break;
1500 1498
 	}
1501 1499
 
1502 1500
 	newedx = cli_readint32(dest) - EC32(optional_hdr32.ImageBase);
1503 1501
 	if(!CLI_ISCONTAINED(exe_sections[i + 1].rva, exe_sections[i + 1].rsz, newedx, 4)) {
1504 1502
 	    cli_dbgmsg("FSG: New ESP (%x) is wrong\n", newedx);
1505
-	    free(src);
1506 1503
 	    break;
1507 1504
 	}
1508 1505
  
1509 1506
 	dest = src + newedx - exe_sections[i + 1].rva;
1510 1507
 	if(!CLI_ISCONTAINED(src, ssize, dest, 32)) {
1511 1508
 	    cli_dbgmsg("FSG: New stack out of bounds\n");
1512
-	    free(src);
1513 1509
 	    break;
1514 1510
 	}
1515 1511
 
... ...
@@ -1520,19 +1471,16 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1520 1520
 
1521 1521
 	if(newedi != exe_sections[i].rva) {
1522 1522
 	    cli_dbgmsg("FSG: Bad destination buffer (edi is %x should be %x)\n", newedi, exe_sections[i].rva);
1523
-	    free(src);
1524 1523
 	    break;
1525 1524
 	}
1526 1525
 
1527 1526
 	if(newesi < exe_sections[i + 1].rva || newesi - exe_sections[i + 1].rva >= exe_sections[i + 1].rsz) {
1528 1527
 	    cli_dbgmsg("FSG: Source buffer out of section bounds\n");
1529
-	    free(src);
1530 1528
 	    break;
1531 1529
 	}
1532 1530
 
1533 1531
 	if(!CLI_ISCONTAINED(exe_sections[i + 1].rva, exe_sections[i + 1].rsz, newebx, 16)) {
1534 1532
 	    cli_dbgmsg("FSG: Array of functions out of bounds\n");
1535
-	    free(src);
1536 1533
 	    break;
1537 1534
 	}
1538 1535
 
... ...
@@ -1545,8 +1493,8 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1545 1545
 	    return CL_EMEM;
1546 1546
 	}
1547 1547
 
1548
-	CLI_UNPTEMP("FSG",(src,dest,exe_sections,0));
1549
-	CLI_UNPRESULTSFSG2("FSG",(unfsg_200(newesi - exe_sections[i + 1].rva + src, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, newedi, EC32(optional_hdr32.ImageBase), newedx, ndesc)),1,(src,dest,0));
1548
+	CLI_UNPTEMP("FSG",(dest,exe_sections,0));
1549
+	CLI_UNPRESULTSFSG2("FSG",(unfsg_200(newesi - exe_sections[i + 1].rva + src, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, newedi, EC32(optional_hdr32.ImageBase), newedx, ndesc)),1,(dest,0));
1550 1550
 	break;
1551 1551
     }
1552 1552
 
... ...
@@ -1571,25 +1519,18 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1571 1571
 	    return CL_CLEAN;
1572 1572
 	}
1573 1573
 
1574
-	if(!(gp = cli_rawaddr(cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase), NULL, 0 , &err, fsize, hdr_size)) && err ) {
1574
+	if(!(t = cli_rawaddr(cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase), NULL, 0 , &err, fsize, hdr_size)) && err ) {
1575 1575
 	    cli_dbgmsg("FSG: Support data out of padding area\n");
1576 1576
 	    break;
1577 1577
 	}
1578 1578
 
1579
-	lseek(desc, gp, SEEK_SET);
1580
-	gp = exe_sections[i + 1].raw - gp;
1579
+	gp = exe_sections[i + 1].raw - t;
1581 1580
 
1582
-	CLI_UNPSIZELIMITS("FSG", gp)
1581
+	CLI_UNPSIZELIMITS("FSG", gp);
1583 1582
 
1584
-	if((support = (char *) cli_malloc(gp)) == NULL) {
1585
-	    free(exe_sections);
1586
-	    return CL_EMEM;
1587
-	}
1588
-
1589
-	if((int)cli_readn(desc, support, gp) != (int)gp) {
1583
+	if(!(support = fmap_need_off_once(map, t, gp))) {
1590 1584
 	    cli_dbgmsg("Can't read %d bytes from padding area\n", gp); 
1591 1585
 	    free(exe_sections);
1592
-	    free(support);
1593 1586
 	    return CL_EREAD;
1594 1587
 	}
1595 1588
 
... ...
@@ -1599,13 +1540,11 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1599 1599
 
1600 1600
 	if(newesi < exe_sections[i + 1].rva || newesi - exe_sections[i + 1].rva >= exe_sections[i + 1].rsz) {
1601 1601
 	    cli_dbgmsg("FSG: Source buffer out of section bounds\n");
1602
-	    free(support);
1603 1602
 	    break;
1604 1603
 	}
1605 1604
 
1606 1605
 	if(newedi != exe_sections[i].rva) {
1607 1606
 	    cli_dbgmsg("FSG: Bad destination (is %x should be %x)\n", newedi, exe_sections[i].rva);
1608
-	    free(support);
1609 1607
 	    break;
1610 1608
 	}
1611 1609
 
... ...
@@ -1628,13 +1567,11 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1628 1628
 	}
1629 1629
 
1630 1630
 	if(t >= gp - 4 || cli_readint32(support + t)) {
1631
-	    free(support);
1632 1631
 	    break;
1633 1632
 	}
1634 1633
 
1635 1634
 	if((sections = (struct cli_exe_section *) cli_malloc((sectcnt + 1) * sizeof(struct cli_exe_section))) == NULL) {
1636 1635
 	    free(exe_sections);
1637
-	    free(support);
1638 1636
 	    return CL_EMEM;
1639 1637
 	}
1640 1638
 
... ...
@@ -1642,25 +1579,15 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1642 1642
 	for(t = 1; t <= (uint32_t)sectcnt; t++)
1643 1643
 	    sections[t].rva = cli_readint32(support + 8 + t * 4) - 1 - EC32(optional_hdr32.ImageBase);
1644 1644
 
1645
-	free(support);
1646
-
1647
-	if((src = (char *) cli_malloc(ssize)) == NULL) {
1648
-	    free(exe_sections);
1649
-	    free(sections);
1650
-	    return CL_EMEM;
1651
-	}
1652
-
1653
-	if(!cli_seeksect(desc, &exe_sections[i + 1]) || (unsigned int) cli_readn(desc, src, ssize) != ssize) {
1645
+	if(!exe_sections[i + 1].rsz || !(src = fmap_need_off_once(map, exe_sections[i + 1].raw, ssize))) {
1654 1646
 	    cli_dbgmsg("Can't read raw data of section %d\n", i);
1655 1647
 	    free(exe_sections);
1656 1648
 	    free(sections);
1657
-	    free(src);
1658 1649
 	    return CL_EREAD;
1659 1650
 	}
1660 1651
 
1661 1652
 	if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
1662 1653
 	    free(exe_sections);
1663
-	    free(src);
1664 1654
 	    free(sections);
1665 1655
 	    return CL_EMEM;
1666 1656
 	}
... ...
@@ -1668,8 +1595,8 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1668 1668
 	oldep = vep + 161 + 6 + cli_readint32(epbuff+163);
1669 1669
 	cli_dbgmsg("FSG: found old EP @%x\n", oldep);
1670 1670
 
1671
-	CLI_UNPTEMP("FSG",(src,dest,sections,exe_sections,0));
1672
-	CLI_UNPRESULTSFSG1("FSG",(unfsg_133(src + newesi - exe_sections[i + 1].rva, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, sections, sectcnt, EC32(optional_hdr32.ImageBase), oldep, ndesc)),1,(src,dest,sections,0));
1671
+	CLI_UNPTEMP("FSG",(dest,sections,exe_sections,0));
1672
+	CLI_UNPRESULTSFSG1("FSG",(unfsg_133(src + newesi - exe_sections[i + 1].rva, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, sections, sectcnt, EC32(optional_hdr32.ImageBase), oldep, ndesc)),1,(dest,sections,0));
1673 1673
 	break; /* were done with 1.33 */
1674 1674
     }
1675 1675
 
... ...
@@ -1679,8 +1606,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1679 1679
 	/* FSG support - v. 1.31 */
1680 1680
 
1681 1681
 	int sectcnt = 0;
1682
-	uint32_t t;
1683
-	uint32_t gp = cli_rawaddr(cli_readint32(epbuff+1) - EC32(optional_hdr32.ImageBase), NULL, 0 , &err, fsize, hdr_size);
1682
+	uint32_t gp, t = cli_rawaddr(cli_readint32(epbuff+1) - EC32(optional_hdr32.ImageBase), NULL, 0 , &err, fsize, hdr_size);
1684 1683
 	char *support;
1685 1684
 	uint32_t newesi = cli_readint32(epbuff+11) - EC32(optional_hdr32.ImageBase);
1686 1685
 	uint32_t newedi = cli_readint32(epbuff+6) - EC32(optional_hdr32.ImageBase);
... ...
@@ -1690,7 +1616,6 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1690 1690
 	ssize = exe_sections[i + 1].rsz;
1691 1691
 	dsize = exe_sections[i].vsz;
1692 1692
 
1693
-
1694 1693
 	if(err) {
1695 1694
 	    cli_dbgmsg("FSG: Support data out of padding area\n");
1696 1695
 	    break;
... ...
@@ -1714,20 +1639,13 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1714 1714
 	    return CL_CLEAN;
1715 1715
 	}
1716 1716
 
1717
-	lseek(desc, gp, SEEK_SET);
1718
-	gp = exe_sections[i + 1].raw - gp;
1717
+	gp = exe_sections[i + 1].raw - t;
1719 1718
 
1720 1719
 	CLI_UNPSIZELIMITS("FSG", gp)
1721 1720
 
1722
-	if((support = (char *) cli_malloc(gp)) == NULL) {
1723
-	    free(exe_sections);
1724
-	    return CL_EMEM;
1725
-	}
1726
-
1727
-	if(cli_readn(desc, support, gp) != (int)gp) {
1721
+	if(!(support = fmap_need_off_once(map, t, gp))) {
1728 1722
 	    cli_dbgmsg("Can't read %d bytes from padding area\n", gp); 
1729 1723
 	    free(exe_sections);
1730
-	    free(support);
1731 1724
 	    return CL_EREAD;
1732 1725
 	}
1733 1726
 
... ...
@@ -1748,13 +1666,11 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1748 1748
 	}
1749 1749
 
1750 1750
 	if(t >= gp-10 || cli_readint32(support + t + 6) != 2) {
1751
-	    free(support);
1752 1751
 	    break;
1753 1752
 	}
1754 1753
 
1755 1754
 	if((sections = (struct cli_exe_section *) cli_malloc((sectcnt + 1) * sizeof(struct cli_exe_section))) == NULL) {
1756 1755
 	    free(exe_sections);
1757
-	    free(support);
1758 1756
 	    return CL_EMEM;
1759 1757
 	}
1760 1758
 
... ...
@@ -1763,25 +1679,21 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1763 1763
 	    sections[t+1].rva = (((support[t*2]|(support[t*2+1]<<8))-2)<<12)-EC32(optional_hdr32.ImageBase);
1764 1764
 	}
1765 1765
 
1766
-	free(support);
1767
-
1768 1766
 	if((src = (char *) cli_malloc(ssize)) == NULL) {
1769 1767
 	    free(exe_sections);
1770 1768
 	    free(sections);
1771 1769
 	    return CL_EMEM;
1772 1770
 	}
1773 1771
 
1774
-	if(!cli_seeksect(desc, &exe_sections[i + 1]) || (unsigned int) cli_readn(desc, src, ssize) != ssize) {
1772
+	if(!exe_sections[i + 1].rsz || !(src = fmap_need_off_once(map, exe_sections[i + 1].raw, ssize))) {
1775 1773
 	    cli_dbgmsg("FSG: Can't read raw data of section %d\n", i);
1776 1774
 	    free(exe_sections);
1777 1775
 	    free(sections);
1778
-	    free(src);
1779 1776
 	    return CL_EREAD;
1780 1777
 	}
1781 1778
 
1782 1779
 	if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
1783 1780
 	    free(exe_sections);
1784
-	    free(src);
1785 1781
 	    free(sections);
1786 1782
 	    return CL_EMEM;
1787 1783
 	}
... ...
@@ -1790,8 +1702,8 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1790 1790
 	oldep = vep + gp + 6 + cli_readint32(src+gp+2+oldep);
1791 1791
 	cli_dbgmsg("FSG: found old EP @%x\n", oldep);
1792 1792
 
1793
-	CLI_UNPTEMP("FSG",(src,dest,sections,exe_sections,0));
1794
-	CLI_UNPRESULTSFSG1("FSG",(unfsg_133(src + newesi - exe_sections[i + 1].rva, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, sections, sectcnt, EC32(optional_hdr32.ImageBase), oldep, ndesc)),1,(src,dest,sections,0));
1793
+	CLI_UNPTEMP("FSG",(dest,sections,exe_sections,0));
1794
+	CLI_UNPRESULTSFSG1("FSG",(unfsg_133(src + newesi - exe_sections[i + 1].rva, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, sections, sectcnt, EC32(optional_hdr32.ImageBase), oldep, ndesc)),1,(dest,sections,0));
1795 1795
 	break; /* were done with 1.31 */
1796 1796
     }
1797 1797
 
... ...
@@ -1817,20 +1729,19 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1817 1817
 	    return CL_EMEM;
1818 1818
 	}
1819 1819
 
1820
-	if((dest = (char *) cli_calloc(dsize + 8192, sizeof(char))) == NULL) {
1821
-	    free(exe_sections);
1822
-	    free(src);
1823
-	    return CL_EMEM;
1824
-	}
1825
-
1826
-	if(!cli_seeksect(desc, &exe_sections[i + 1]) || (unsigned int) cli_readn(desc, src, ssize) != ssize) {
1820
+	if(!exe_sections[i + 1].raw || !(src = fmap_need_off_once(map, exe_sections[i + 1].raw, ssize))) {
1827 1821
 	    cli_dbgmsg("UPX: Can't read raw data of section %d\n", i+1);
1828 1822
 	    free(exe_sections);
1829
-	    free(src);
1830 1823
 	    free(dest);
1831 1824
 	    return CL_EREAD;
1832 1825
 	}
1833 1826
 
1827
+	if((dest = (char *) cli_calloc(dsize + 8192, sizeof(char))) == NULL) {
1828
+	    free(exe_sections);
1829
+	    return CL_EMEM;
1830
+	}
1831
+
1832
+
1834 1833
 	/* try to detect UPX code */
1835 1834
 	if(cli_memstr(UPX_NRV2B, 24, epbuff + 0x69, 13) || cli_memstr(UPX_NRV2B, 24, epbuff + 0x69 + 8, 13)) {
1836 1835
 	    cli_dbgmsg("UPX: Looks like a NRV2B decompression routine\n");
... ...
@@ -1904,13 +1815,11 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1904 1904
 
1905 1905
 	if(!upx_success) {
1906 1906
 	    cli_dbgmsg("UPX: All decompressors failed\n");
1907
-	    free(src);
1908 1907
 	    free(dest);
1909 1908
 	}
1910 1909
     }
1911 1910
 
1912 1911
     if(upx_success) {
1913
-	free(src);
1914 1912
 	free(exe_sections);
1915 1913
 
1916 1914
 	CLI_UNPTEMP("UPX/FSG",(dest,0));
... ...
@@ -1978,7 +1887,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1978 1978
 
1979 1979
 	    for(i = 0 ; i < nsections; i++) {
1980 1980
 		if(exe_sections[i].raw) {
1981
-		    if(!cli_seeksect(desc, &exe_sections[i]) || (unsigned int) cli_readn(desc, dest + exe_sections[i].rva - min, exe_sections[i].ursz) != exe_sections[i].ursz) {
1981
+		    if(!exe_sections[i].rsz || fmap_readn(map, dest + exe_sections[i].rva - min, exe_sections[i].raw, exe_sections[i].ursz) != exe_sections[i].ursz) {
1982 1982
 			free(exe_sections);
1983 1983
 			free(dest);
1984 1984
 			return CL_CLEAN;
... ...
@@ -2007,8 +1916,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
2007 2007
 	    return CL_EMEM;
2008 2008
 	}
2009 2009
 
2010
-	lseek(desc, 0, SEEK_SET);
2011
-	if((size_t) cli_readn(desc, spinned, fsize) != fsize) {
2010
+	if((size_t) fmap_readn(map, spinned, 0, fsize) != fsize) {
2012 2011
 	    cli_dbgmsg("PESpin: Can't read %lu bytes\n", (unsigned long)fsize);
2013 2012
 	    free(spinned);
2014 2013
 	    free(exe_sections);
... ...
@@ -2072,8 +1980,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
2072 2072
 	    return CL_EMEM;
2073 2073
 	}
2074 2074
 
2075
-	lseek(desc, 0, SEEK_SET);
2076
-	if((size_t) cli_readn(desc, spinned, fsize) != fsize) {
2075
+	if((size_t) fmap_readn(map, spinned, 0, fsize) != fsize) {
2077 2076
 	    cli_dbgmsg("yC: Can't read %lu bytes\n", (unsigned long)fsize);
2078 2077
 	    free(spinned);
2079 2078
 	    free(exe_sections);
... ...
@@ -2110,8 +2017,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
2110 2110
 	    free(exe_sections);
2111 2111
 	    return CL_EMEM;
2112 2112
 	}
2113
-	lseek(desc, 0, SEEK_SET);
2114
-	if((size_t) cli_readn(desc, src, head) != head) {
2113
+	if((size_t) fmap_readn(map, src, 0, head) != head) {
2115 2114
 	    cli_dbgmsg("WWPack: Can't read %d bytes from headers\n", head);
2116 2115
 	    free(src);
2117 2116
 	    free(exe_sections);
... ...
@@ -2119,9 +2025,8 @@ int cli_scanpe(int desc, cli_ctx *ctx)
2119 2119
 	}
2120 2120
         for(i = 0 ; i < (unsigned int)nsections-1; i++) {
2121 2121
 	    if(!exe_sections[i].rsz) continue;
2122
-	    if(!cli_seeksect(desc, &exe_sections[i])) break;
2123 2122
             if(!CLI_ISCONTAINED(src, ssize, src+exe_sections[i].rva, exe_sections[i].rsz)) break;
2124
-            if(cli_readn(desc, src+exe_sections[i].rva, exe_sections[i].rsz)!=exe_sections[i].rsz) break;
2123
+            if(fmap_readn(map, src+exe_sections[i].rva, exe_sections[i].raw, exe_sections[i].rsz)!=exe_sections[i].rsz) break;
2125 2124
         }
2126 2125
         if(i+1!=nsections) {
2127 2126
             cli_dbgmsg("WWpack: Probably hacked/damaged file.\n");
... ...
@@ -2133,7 +2038,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
2133 2133
 	    free(exe_sections);
2134 2134
 	    return CL_EMEM;
2135 2135
 	}
2136
-	if(!cli_seeksect(desc, &exe_sections[nsections - 1]) || (size_t) cli_readn(desc, packer, exe_sections[nsections - 1].rsz) != exe_sections[nsections - 1].rsz) {
2136
+	if(!exe_sections[nsections - 1].rsz || (size_t) fmap_readn(map, packer, exe_sections[nsections - 1].raw, exe_sections[nsections - 1].rsz) != exe_sections[nsections - 1].rsz) {
2137 2137
 	    cli_dbgmsg("WWPack: Can't read %d bytes from wwpack sect\n", exe_sections[nsections - 1].rsz);
2138 2138
 	    free(src);
2139 2139
 	    free(packer);
... ...
@@ -2165,9 +2070,8 @@ int cli_scanpe(int desc, cli_ctx *ctx)
2165 2165
 	}
2166 2166
         for(i = 0 ; i < (unsigned int)nsections; i++) {
2167 2167
 	    if(!exe_sections[i].rsz) continue;
2168
-	    if(!cli_seeksect(desc, &exe_sections[i])) break;
2169 2168
             if(!CLI_ISCONTAINED(src, ssize, src+exe_sections[i].rva, exe_sections[i].rsz)) break;
2170
-            if(cli_readn(desc, src+exe_sections[i].rva, exe_sections[i].rsz)!=exe_sections[i].rsz) break;
2169
+            if(fmap_readn(map, src+exe_sections[i].rva, exe_sections[i].raw, exe_sections[i].rsz)!=exe_sections[i].rsz) break;
2171 2170
         }
2172 2171
         if(i!=nsections) {
2173 2172
             cli_dbgmsg("Aspack: Probably hacked/damaged Aspack file.\n");
... ...
@@ -2186,14 +2090,13 @@ int cli_scanpe(int desc, cli_ctx *ctx)
2186 2186
 	uint32_t eprva = vep;
2187 2187
 	uint32_t start_of_stuff, ssize, dsize, rep = ep;
2188 2188
 	unsigned int nowinldr;
2189
-	char nbuff[24];
2189
+	char *nbuff;
2190 2190
 	char *src=epbuff, *dest;
2191 2191
 
2192 2192
 	if (*epbuff=='\xe9') { /* bitched headers */
2193 2193
 	    eprva = cli_readint32(epbuff+1)+vep+5;
2194 2194
 	    if (!(rep = cli_rawaddr(eprva, exe_sections, nsections, &err, fsize, hdr_size)) && err) break;
2195
-	    if (lseek(desc, rep, SEEK_SET)==-1) break;
2196
-	    if (cli_readn(desc, nbuff, 24)!=24) break;
2195
+	    if (!(nbuff = fmap_need_off_once(map, rep, 24))) break;
2197 2196
 	    src = nbuff;
2198 2197
 	}
2199 2198
 
... ...
@@ -2202,11 +2105,9 @@ int cli_scanpe(int desc, cli_ctx *ctx)
2202 2202
 	nowinldr = 0x54-cli_readint32(src+17);
2203 2203
 	cli_dbgmsg("NsPack: Found *start_of_stuff @delta-%x\n", nowinldr);
2204 2204
 
2205
-	if (lseek(desc, rep-nowinldr, SEEK_SET)==-1) break;
2206
-	if (cli_readn(desc, nbuff, 4)!=4) break;
2205
+	if(!(nbuff = fmap_need_off_once(map, rep-nowinldr, 4))) break;
2207 2206
 	start_of_stuff=rep+cli_readint32(nbuff);
2208
-	if (lseek(desc, start_of_stuff, SEEK_SET)==-1) break;
2209
-	if (cli_readn(desc, nbuff, 20)!=20) break;
2207
+	if(!(nbuff = fmap_need_off_once(map, start_of_stuff, 20))) break;
2210 2208
 	src = nbuff;
2211 2209
 	if (!cli_readint32(nbuff)) {
2212 2210
 	    start_of_stuff+=4; /* FIXME: more to do */
... ...
@@ -2218,39 +2119,31 @@ int cli_scanpe(int desc, cli_ctx *ctx)
2218 2218
 
2219 2219
 	CLI_UNPSIZELIMITS("NsPack", MAX(ssize,dsize));
2220 2220
 
2221
-	if ( !ssize || !dsize || dsize != exe_sections[0].vsz) break;
2222
-	if (lseek(desc, start_of_stuff, SEEK_SET)==-1) break;
2221
+	if (!ssize || !dsize || dsize != exe_sections[0].vsz) break;
2223 2222
 	if (!(dest=cli_malloc(dsize))) break;
2224 2223
 	/* memset(dest, 0xfc, dsize); */
2225 2224
 
2226
-	if (!(src=cli_malloc(ssize))) {
2225
+	if(!(src = fmap_need_off(map, start_of_stuff, ssize))) {
2227 2226
 	    free(dest);
2228 2227
 	    break;
2229 2228
 	}
2230 2229
 	/* memset(src, 0x00, ssize); */
2231
-	cli_readn(desc, src, ssize);
2232 2230
 
2233 2231
 	eprva+=0x27a;
2234 2232
 	if (!(rep = cli_rawaddr(eprva, exe_sections, nsections, &err, fsize, hdr_size)) && err) {
2235 2233
 	  free(dest);
2236
-	  free(src);
2237
-	  break;
2238
-	}
2239
-	if (lseek(desc, rep, SEEK_SET)==-1) {
2240
-	  free(dest);
2241
-	  free(src);
2242 2234
 	  break;
2243 2235
 	}
2244
-	if (cli_readn(desc, nbuff, 5)!=5) {
2236
+	if(!(nbuff = fmap_need_off_once(map, rep, 5))) {
2245 2237
 	  free(dest);
2246
-	  free(src);
2247 2238
 	  break;
2248 2239
 	}
2240
+	fmap_unneed_off(map, start_of_stuff, ssize);
2249 2241
 	eprva=eprva+5+cli_readint32(nbuff+1);
2250 2242
 	cli_dbgmsg("NsPack: OEP = %08x\n", eprva);
2251 2243
 
2252
-	CLI_UNPTEMP("NsPack",(src,dest,exe_sections,0));
2253
-	CLI_UNPRESULTS("NsPack",(unspack(src, dest, ctx, exe_sections[0].rva, EC32(optional_hdr32.ImageBase), eprva, ndesc)),0,(src,dest,0));
2244
+	CLI_UNPTEMP("NsPack",(dest,exe_sections,0));
2245
+	CLI_UNPRESULTS("NsPack",(unspack(src, dest, ctx, exe_sections[0].rva, EC32(optional_hdr32.ImageBase), eprva, ndesc)),0,(dest,0));
2254 2246
 	break;
2255 2247
     }
2256 2248
 
... ...
@@ -128,7 +128,7 @@ struct pe_image_section_hdr {
128 128
     uint32_t Characteristics;
129 129
 };
130 130
 
131
-int cli_scanpe(int desc, cli_ctx *ctx);
131
+int cli_scanpe(cli_ctx *ctx);
132 132
 
133 133
 int cli_peheader(int desc, struct cli_exe_info *peinfo);
134 134
 
... ...
@@ -2161,7 +2161,7 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx)
2161 2161
 	 */
2162 2162
 	case CL_TYPE_MSEXE:
2163 2163
 	    if(SCAN_PE && ctx->dconf->pe)
2164
-		ret = cli_scanpe(desc, ctx);
2164
+		ret = cli_scanpe(ctx);
2165 2165
 	    break;
2166 2166
 
2167 2167
 	default: