~ubuntu-branches/ubuntu/dapper/clamav/dapper

« back to all changes in this revision

Viewing changes to libclamav/pe.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephen Gran
  • Date: 2006-01-10 02:55:18 UTC
  • mto: This revision was merged to the branch mainline in revision 5.
  • Revision ID: james.westby@ubuntu.com-20060110025518-92bhgfe911byl3bc
Tags: upstream-0.88
ImportĀ upstreamĀ versionĀ 0.88

Show diffs side-by-side

added added

removed removed

Lines of Context:
48
48
#define IMAGE_OPTIONAL_SIGNATURE    0x010b
49
49
 
50
50
#define DETECT_BROKEN               (options & CL_SCAN_BLOCKBROKEN)
 
51
#define BLOCKMAX                    (options & CL_SCAN_BLOCKMAX)
51
52
 
52
53
#define UPX_NRV2B "\x11\xdb\x11\xc9\x01\xdb\x75\x07\x8b\x1e\x83\xee\xfc\x11\xdb\x11\xc9\x11\xc9\x75\x20\x41\x01\xdb"
53
54
#define UPX_NRV2D "\x83\xf0\xff\x74\x78\xd1\xf8\x89\xc5\xeb\x0b\x01\xdb\x75\x07\x8b\x1e\x83\xee\xfc\x11\xdb\x11\xc9"
146
147
}
147
148
*/
148
149
 
149
 
int cli_scanpe(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
 
150
int cli_scanpe(int desc, const char **virname, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
150
151
{
151
152
        uint16_t e_magic; /* DOS signature ("MZ") */
152
153
        uint16_t nsections;
160
161
        char sname[9], buff[4096], *tempfile;
161
162
        unsigned int i, found, upx_success = 0, min = 0, max = 0, err, broken = 0;
162
163
        unsigned int ssize = 0, dsize = 0, dll = 0;
163
 
        int (*upxfn)(char *, int , char *, int *, uint32_t, uint32_t, uint32_t) = NULL;
 
164
        int (*upxfn)(char *, uint32_t , char *, uint32_t *, uint32_t, uint32_t, uint32_t) = NULL;
164
165
        char *src = NULL, *dest = NULL;
165
166
        int ndesc, ret;
166
167
 
332
333
    cli_dbgmsg("SizeOfOptionalHeader: %d\n", EC16(file_hdr.SizeOfOptionalHeader));
333
334
 
334
335
    if(EC16(file_hdr.SizeOfOptionalHeader) != sizeof(struct pe_image_optional_hdr)) {
335
 
        cli_warnmsg("Broken PE header detected.\n");
336
 
        if(DETECT_BROKEN) {
337
 
            if(virname)
338
 
                *virname = "Broken.Executable";
339
 
            return CL_VIRUS;
340
 
        }
 
336
        /* Support for PE32+ binaries available in CVS */
341
337
        return CL_CLEAN;
342
338
    }
343
339
 
597
593
                if(limits && limits->maxfilesize && (ssize > limits->maxfilesize || dsize > limits->maxfilesize)) {
598
594
                    cli_dbgmsg("FSG: Sizes exceeded (ssize: %d, dsize: %d, max: %lu)\n", ssize, dsize , limits->maxfilesize);
599
595
                    free(section_hdr);
600
 
                    return CL_CLEAN;
 
596
                    if(BLOCKMAX) {
 
597
                        *virname = "PE.FSG.ExceededFileSize";
 
598
                         return CL_VIRUS;
 
599
                    } else {
 
600
                         return CL_CLEAN;
 
601
                    }
601
602
                }
602
603
 
603
604
                if(ssize <= 0x19 || dsize <= ssize) {
665
666
                    break;
666
667
                }
667
668
 
668
 
                /* FIXME: unused atm, needed for pe rebuilding */
669
 
                cli_dbgmsg("FSG: found old EP @%x\n", cli_readint32(newebx + 12 - EC32(section_hdr[i + 1].VirtualAddress) + src) - EC32(optional_hdr.ImageBase));
 
669
                newedx=cli_readint32(newebx + 12 - EC32(section_hdr[i + 1].VirtualAddress) + src) - EC32(optional_hdr.ImageBase);
 
670
                cli_dbgmsg("FSG: found old EP @%x\n",newedx);
670
671
 
671
672
                if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
672
673
                    free(section_hdr);
674
675
                    return CL_EMEM;
675
676
                }
676
677
 
677
 
                if(unfsg_200(newesi - EC32(section_hdr[i + 1].VirtualAddress) + src, dest, ssize + EC32(section_hdr[i + 1].VirtualAddress) - newesi, dsize) == -1) {
678
 
                    cli_dbgmsg("FSG: Unpacking failed\n");
679
 
                    free(src);
680
 
                    free(dest);
681
 
                    break;
 
678
                tempfile = cli_gentemp(NULL);
 
679
                if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
 
680
                  cli_dbgmsg("FSG: Can't create file %s\n", tempfile);
 
681
                  free(tempfile);
 
682
                  free(section_hdr);
 
683
                  free(src);
 
684
                  free(dest);
 
685
                  return CL_EIO;
 
686
                }
 
687
 
 
688
                switch (unfsg_200(newesi - EC32(section_hdr[i + 1].VirtualAddress) + src, dest, ssize + EC32(section_hdr[i + 1].VirtualAddress) - newesi, dsize, newedi, EC32(optional_hdr.ImageBase), newedx, ndesc)) {
 
689
                case 1: /* Everything OK */
 
690
                  cli_dbgmsg("FSG: Unpacked and rebuilt executable saved in %s\n", tempfile);
 
691
                  free(src);
 
692
                  free(dest);
 
693
                  fsync(ndesc);
 
694
                  lseek(ndesc, 0, SEEK_SET);
 
695
 
 
696
                  cli_dbgmsg("***** Scanning rebuilt PE file *****\n");
 
697
                  if(cli_magic_scandesc(ndesc, virname, scanned, root, limits, options, arec, mrec) == CL_VIRUS) {
 
698
                    free(section_hdr);
 
699
                    close(ndesc);
 
700
                    if(!cli_leavetemps_flag)
 
701
                      unlink(tempfile);
 
702
                    free(tempfile);
 
703
                    return CL_VIRUS;
 
704
                  }
 
705
                  close(ndesc);
 
706
                  if(!cli_leavetemps_flag)
 
707
                    unlink(tempfile);
 
708
                  free(tempfile);
 
709
                  free(section_hdr);
 
710
                  return CL_CLEAN;
 
711
 
 
712
                case 0: /* We've got an unpacked buffer, no exe though */
 
713
                  cli_dbgmsg("FSG: Successfully decompressed\n");
 
714
                  close(ndesc);
 
715
                  free(tempfile);
 
716
                  found = 0;
 
717
                  upx_success = 1;
 
718
                  break; /* Go and scan the buffer! */
 
719
 
 
720
                default: /* Everything gone wrong */
 
721
                  cli_dbgmsg("FSG: Unpacking failed\n");
 
722
                  close(ndesc);
 
723
                  free(tempfile);
 
724
                  free(src);
 
725
                  free(dest);
 
726
                  break;
682
727
                }
683
728
 
684
 
                found = 0;
685
 
                upx_success = 1;
686
 
                cli_dbgmsg("FSG: Successfully decompressed\n");
 
729
                break; /* were done with 2 */
687
730
            }
688
731
        }
689
732
 
704
747
                if(limits && limits->maxfilesize && (ssize > limits->maxfilesize || dsize > limits->maxfilesize)) {
705
748
                    cli_dbgmsg("FSG: Sizes exceeded (ssize: %d, dsize: %d, max: %lu)\n", ssize, dsize, limits->maxfilesize);
706
749
                    free(section_hdr);
707
 
                    return CL_CLEAN;
 
750
                    if(BLOCKMAX) {
 
751
                        *virname = "PE.FSG.ExceededFileSize";
 
752
                         return CL_VIRUS;
 
753
                    } else {
 
754
                         return CL_CLEAN;
 
755
                    }
708
756
                }
709
757
 
710
758
                if(ssize <= 0x19 || dsize <= ssize) {
724
772
                if(limits && limits->maxfilesize && (unsigned int) gp > limits->maxfilesize) {
725
773
                    cli_dbgmsg("FSG: Buffer size exceeded (size: %d, max: %lu)\n", gp, limits->maxfilesize);
726
774
                    free(section_hdr);
727
 
                    return CL_CLEAN;
 
775
                    if(BLOCKMAX) {
 
776
                        *virname = "PE.FSG.ExceededFileSize";
 
777
                         return CL_VIRUS;
 
778
                    } else {
 
779
                         return CL_CLEAN;
 
780
                    }
728
781
                }
729
782
 
730
783
                if((support = (char *) cli_malloc(gp)) == NULL) {
914
967
                if(limits && limits->maxfilesize && (ssize > limits->maxfilesize || dsize > limits->maxfilesize)) {
915
968
                    cli_dbgmsg("FSG: Sizes exceeded (ssize: %d, dsize: %d, max: %lu)\n", ssize, dsize, limits->maxfilesize);
916
969
                    free(section_hdr);
917
 
                    return CL_CLEAN;
 
970
                    if(BLOCKMAX) {
 
971
                        *virname = "PE.FSG.ExceededFileSize";
 
972
                         return CL_VIRUS;
 
973
                    } else {
 
974
                         return CL_CLEAN;
 
975
                    }
918
976
                }
919
977
 
920
978
                if(ssize <= 0x19 || dsize <= ssize) {
934
992
                if(limits && limits->maxfilesize && (unsigned int) gp > limits->maxfilesize) {
935
993
                    cli_dbgmsg("FSG: Buffer size exceeded (size: %d, max: %lu)\n", gp, limits->maxfilesize);
936
994
                    free(section_hdr);
937
 
                    return CL_CLEAN;
 
995
                    if(BLOCKMAX) {
 
996
                        *virname = "PE.FSG.ExceededFileSize";
 
997
                         return CL_VIRUS;
 
998
                    } else {
 
999
                         return CL_CLEAN;
 
1000
                    }
938
1001
                }
939
1002
 
940
1003
                if((support = (char *) cli_malloc(gp)) == NULL) {
1055
1118
                        free(sections);
1056
1119
                        found = 0;
1057
1120
                        upx_success = 1;
1058
 
                        break; /* Go and scan the buffer! */
 
1121
                        break; /* Go and scan the decompressed data */
1059
1122
 
1060
1123
                    default: /* Everything gone wrong */
1061
1124
                        cli_dbgmsg("FSG: Unpacking failed\n");
1094
1157
            if(limits && limits->maxfilesize && (ssize > limits->maxfilesize || dsize > limits->maxfilesize)) {
1095
1158
                cli_dbgmsg("UPX: Sizes exceeded (ssize: %d, dsize: %d, max: %lu)\n", ssize, dsize , limits->maxfilesize);
1096
1159
                free(section_hdr);
1097
 
                return CL_CLEAN;
 
1160
                if(BLOCKMAX) {
 
1161
                    *virname = "PE.UPX.ExceededFileSize";
 
1162
                    return CL_VIRUS;
 
1163
                } else {
 
1164
                    return CL_CLEAN;
 
1165
                }
1098
1166
            }
1099
1167
 
1100
1168
            if(ssize <= 0x19 || dsize <= ssize) { /* FIXME: What are reasonable values? */
1283
1351
            if(limits && limits->maxfilesize && dsize > limits->maxfilesize) {
1284
1352
                cli_dbgmsg("Petite: Size exceeded (dsize: %d, max: %lu)\n", dsize, limits->maxfilesize);
1285
1353
                free(section_hdr);
1286
 
                return CL_CLEAN;
 
1354
                if(BLOCKMAX) {
 
1355
                    *virname = "PE.Petite.ExceededFileSize";
 
1356
                    return CL_VIRUS;
 
1357
                } else {
 
1358
                    return CL_CLEAN;
 
1359
                }
1287
1360
            }
1288
1361
 
1289
1362
            if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
1422
1495
    }
1423
1496
 
1424
1497
    if(EC16(file_hdr.SizeOfOptionalHeader) != sizeof(struct pe_image_optional_hdr)) {
1425
 
        cli_warnmsg("Broken PE header detected.\n");
1426
1498
        return -1;
1427
1499
    }
1428
1500