try to detect broken executables

git-svn: trunk@724
remotes/push_mirror/metadata
Tomasz Kojm 21 years ago
parent f12d249838
commit 20c3d44d09
  1. 9
      clamav-devel/ChangeLog
  2. 6
      clamav-devel/clamd/server-th.c
  3. 4
      clamav-devel/clamscan/clamscan.c
  4. 3
      clamav-devel/clamscan/manager.c
  5. 1
      clamav-devel/clamscan/options.c
  6. 7
      clamav-devel/docs/man/clamav.conf.5
  7. 5
      clamav-devel/docs/man/clamscan.1
  8. 5
      clamav-devel/etc/clamav.conf
  9. 1
      clamav-devel/libclamav/clamav.h
  10. 62
      clamav-devel/libclamav/pe.c
  11. 1
      clamav-devel/shared/cfgparser.c

@ -1,3 +1,12 @@
Wed Aug 4 22:03:56 CEST 2004 (tk)
----------------------------------
* libclamav: pe: improve detection of broken executable files
* libclamav: new scan option CL_BROKEN (report broken executables as
Broken.Executable)
* clamscan: new option --detect-broken
* clamd: new directive DetectBrokenExecutables
* docs: update manual pages
Wed Aug 4 19:59:54 BST 2004 (njh)
----------------------------------
* libclamav: Improved the decoding of multipart messages and MIME headers

@ -314,6 +314,12 @@ int acceptloop_th(int socketd, struct cl_node *root, const struct cfgstruct *cop
if(cfgopt(copt, "ScanPE")) {
logg("Portable Executable support enabled.\n");
options |= CL_PE;
if(cfgopt(copt, "DetectBrokenExecutables")) {
logg("Detection of broken executables enabled.\n");
options |= CL_BROKEN;
}
} else {
logg("Portable Executable support disabled.\n");
}

@ -224,10 +224,12 @@ void help(void)
mprintf(" --no-ole2 Disable OLE2 support\n");
mprintf(" --no-html Disable HTML support\n");
mprintf(" --no-archive Disable libclamav archive support\n");
mprintf(" --block-encrypted Block encrypted archives.\n");
mprintf(" --detect-broken Try to detect broken executable files\n");
mprintf(" --block-encrypted Block encrypted archives\n");
mprintf(" --max-space=#n Extract first #n kilobytes only\n");
mprintf(" --max-files=#n Extract first #n files only\n");
mprintf(" --max-recursion=#n Maximal recursion level\n");
mprintf(" --max-ratio=#n Maximum compression ratio limit\n");
mprintf(" --unzip[=FULLPATH] Enable support for .zip files\n");
mprintf(" --unrar[=FULLPATH] Enable support for .rar files\n");
mprintf(" --arj[=FULLPATH] Enable support for .arj files\n");

@ -421,6 +421,9 @@ int scanfile(const char *filename, struct cl_node *root, const struct passwd *us
else
options |= CL_ARCHIVE;
if(optl(opt, "detect-broken"))
options |= CL_BROKEN;
if(optl(opt, "block-encrypted"))
options |= CL_ENCRYPTED;

@ -89,6 +89,7 @@ int main(int argc, char **argv)
{"max-recursion", 1, 0, 0},
{"disable-archive", 0, 0, 0},
{"no-archive", 0, 0, 0},
{"detect-broken", 0, 0, 0},
{"block-encrypted", 0, 0, 0},
{"no-pe", 0, 0, 0},
{"no-ole2", 0, 0, 0},

@ -1,5 +1,5 @@
.\" Manual page created by Tomasz Kojm, 20021001.
.TH "clamav.conf" "5" "March 14, 2004" "Tomasz Kojm" "Clam AntiVirus"
.TH "clamav.conf" "5" "August 4, 2004" "Tomasz Kojm" "Clam AntiVirus"
.SH "NAME"
.LP
\fBclamav.conf\fR \- a configuration file for Clam AntiVirus Daemon
@ -164,6 +164,11 @@ PE stands for Portable Executable \- it's an executable file format used in all
.br
Default: enabled.
.TP
\fBDetectBrokenExecutables\fR
With this option clamav will try to detect broken executables and mark them as Broken.Executable.
.br
Default: disabled.
.TP
\fBScanOLE2\fR
Enables scanning of Microsoft Office document macros.
.br

@ -1,5 +1,5 @@
.\" Manual page created by Tomasz Kojm, 14/15 IV 2002
.TH "clamscan" "1" "March 14, 2004" "Tomasz Kojm" "Clam AntiVirus"
.TH "clamscan" "1" "August 4, 2004" "Tomasz Kojm" "Clam AntiVirus"
.SH "NAME"
.LP
clamscan \- scan files and directories against viruses
@ -82,6 +82,9 @@ Disable support for HTML detection and normalisation.
\fB\-\-no\-archive\fR
Disable archive support built in libclamav.
.TP
\fB\-\-detect\-broken\fR
Mark broken executables as viruses (Broken.Executable).
.TP
\fB\-\-block\-encrypted\fR
Mark encrypted archives as viruses (Encrypted.Zip, Encrypted.RAR).
.TP

@ -144,6 +144,11 @@ MaxDirectoryRecursion 15
# required for decompression of popular executable packers such as UPX.
ScanPE
# With this option clamav will try to detect broken executables and mark
# them as Broken.Executable
#DetectBrokenExecutables
##
## Documents
##

@ -73,6 +73,7 @@ extern "C"
#define CL_ENCRYPTED 16
#define CL_HTML 32
#define CL_PE 64
#define CL_BROKEN 128
struct cli_bm_patt {

@ -42,6 +42,8 @@
#define IMAGE_NT_SIGNATURE 0x00004550
#define IMAGE_OPTIONAL_SIGNATURE 0x010b
#define DETECT_BROKEN (options & CL_BROKEN)
#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"
#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"
#define UPX_NRV2E "\xeb\x52\x31\xc9\x83\xe8\x03\x72\x11\xc1\xe0\x08\x8a\x06\x46\x83\xf0\xff\x74\x75\xd1\xf8\x89\xc5"
@ -213,7 +215,6 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
return CL_CLEAN;
}
/* cli_dbgmsg("Machine type: "); */
switch(EC16(file_hdr.Machine)) {
case 0x14c:
cli_dbgmsg("Machine type: 80386\n");
@ -253,12 +254,22 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
if(EC16(file_hdr.SizeOfOptionalHeader) != sizeof(struct pe_image_optional_hdr)) {
cli_warnmsg("Broken PE header detected.\n");
if(DETECT_BROKEN) {
if(virname)
*virname = "Broken.Executable";
return CL_VIRUS;
}
return CL_CLEAN;
}
if(read(desc, &optional_hdr, sizeof(struct pe_image_optional_hdr)) != sizeof(struct pe_image_optional_hdr)) {
cli_dbgmsg("Can't optional file header\n");
return CL_EIO;
if(DETECT_BROKEN) {
if(virname)
*virname = "Broken.Executable";
return CL_VIRUS;
}
return CL_CLEAN;
}
cli_dbgmsg("MajorLinkerVersion: %d\n", optional_hdr.MajorLinkerVersion);
@ -304,12 +315,23 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
return CL_EMEM;
}
if(fstat(desc, &sb) == -1) {
cli_dbgmsg("fstat failed\n");
free(section_hdr);
return CL_EIO;
}
for(i = 0; i < nsections; i++) {
if(read(desc, &section_hdr[i], sizeof(struct pe_image_section_hdr)) != sizeof(struct pe_image_section_hdr)) {
cli_dbgmsg("Can't read section header\n");
cli_dbgmsg("Possibly broken PE file\n");
free(section_hdr);
if(DETECT_BROKEN) {
if(virname)
*virname = "Broken.Executable";
return CL_VIRUS;
}
return CL_CLEAN;
}
@ -339,6 +361,17 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
cli_dbgmsg("Section's memory is executable\n");
cli_dbgmsg("------------------------------------\n");
if(EC32(section_hdr[i].PointerToRawData) + EC32(section_hdr[i].SizeOfRawData) > sb.st_size) {
cli_dbgmsg("Possibly broken PE file - Section %d out of file (Offset@ %d, Rsize %d, Total filesize %d)\n", i, EC32(section_hdr[i].PointerToRawData), EC32(section_hdr[i].SizeOfRawData), sb.st_size);
free(section_hdr);
if(DETECT_BROKEN) {
if(virname)
*virname = "Broken.Executable";
return CL_VIRUS;
}
return CL_CLEAN;
}
if(!i) {
min = EC32(section_hdr[i].VirtualAddress);
max = EC32(section_hdr[i].VirtualAddress) + EC32(section_hdr[i].SizeOfRawData);
@ -349,33 +382,22 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
if(EC32(section_hdr[i].VirtualAddress) + EC32(section_hdr[i].SizeOfRawData) > max)
max = EC32(section_hdr[i].VirtualAddress) + EC32(section_hdr[i].SizeOfRawData);
}
}
if(fstat(desc, &sb) == -1) {
cli_dbgmsg("fstat failed\n");
free(section_hdr);
return CL_EIO;
}
if((ep = cli_rawaddr(EC32(optional_hdr.AddressOfEntryPoint), section_hdr, nsections)) == -1) {
cli_dbgmsg("Possibly broken PE file\n");
broken = 1;
}
/* simple sanity check */
if(!broken && EC32(section_hdr[nsections - 1].PointerToRawData) + EC32(section_hdr[nsections - 1].SizeOfRawData) > sb.st_size) {
cli_dbgmsg("Possibly broken PE file - Section %d out of file (Offset@ %d, Rsize %d, Total filesize %d, EP@ %d)\n", nsections - 1, EC32(section_hdr[nsections - 1].PointerToRawData), EC32(section_hdr[nsections - 1].SizeOfRawData), sb.st_size, ep);
broken = 1;
}
if(broken) {
free(section_hdr);
if(DETECT_BROKEN) {
if(virname)
*virname = "Broken.Executable";
return CL_VIRUS;
}
return CL_CLEAN;
}
cli_dbgmsg("EntryPoint offset: 0x%x (%d)\n", ep, ep);
/* UPX support */
/* try to find the first section with physical size == 0 */
@ -559,8 +581,10 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
found = 2;
lseek(desc, ep, SEEK_SET);
if(read(desc, buff, 200) != 200)
if(read(desc, buff, 200) != 200) {
free(section_hdr);
return CL_EIO;
}
if(buff[0] != '\xb8' || cli_readint32(buff + 1) != EC32(section_hdr[nsections - 1].VirtualAddress) + EC32(optional_hdr.ImageBase)) {
if(buff[0] != '\xb8' || cli_readint32(buff + 1) != EC32(section_hdr[nsections - 2].VirtualAddress) + EC32(optional_hdr.ImageBase))

@ -63,6 +63,7 @@ struct cfgstruct *parsecfg(const char *cfgfile, int messages)
{"TemporaryDirectory", OPT_STR},
{"MaxFileSize", OPT_COMPSIZE},
{"ScanPE", OPT_NOARG},
{"DetectBrokenExecutables", OPT_NOARG},
{"ScanMail", OPT_NOARG},
{"ScanHTML", OPT_NOARG},
{"ScanOLE2", OPT_NOARG},

Loading…
Cancel
Save