[Pkg-clamav-commits] [SCM] Debian repository for ClamAV branch, debian/unstable, updated. debian/0.95+dfsg-1-6156-g094ec9b

Tomasz Kojm tkojm at clamav.net
Sun Apr 4 00:56:52 UTC 2010


The following commit has been merged in the debian/unstable branch:
commit cb2337d4d941b38c4056315690d24c28a8662c5d
Author: Tomasz Kojm <tkojm at clamav.net>
Date:   Wed Jul 8 15:01:17 2009 +0200

    libclamav: initial support for Mach-O executables (part of bb#1592)

diff --git a/libclamav/macho.c b/libclamav/macho.c
new file mode 100644
index 0000000..4791f36
--- /dev/null
+++ b/libclamav/macho.c
@@ -0,0 +1,398 @@
+/*
+ *  Copyright (C) 2009 Sourcefire, Inc.
+ *
+ *  Authors: Tomasz Kojm <tkojm at clamav.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA 02110-1301, USA.
+ */
+
+/* TODO:
+ *  - handle LC_THREAD
+ *  - integrate with the matcher
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "clamav.h"
+#include "cltypes.h"
+#include "others.h"
+#include "macho.h"
+#include "execs.h"
+
+#define EC32(v, conv)	(conv ? cbswap32(v) : v)
+#define EC64(v, conv)	(conv ? cbswap64(v) : v)
+
+struct macho_hdr
+{
+    uint32_t magic;
+    uint32_t cpu_type;
+    uint32_t cpu_subtype;
+    uint32_t filetype;
+    uint32_t ncmds;
+    uint32_t sizeofcmds;
+    uint32_t flags;
+};
+
+struct macho_load_cmd
+{
+    uint32_t cmd;
+    uint32_t cmdsize;
+};
+
+struct macho_segment_cmd
+{
+    char segname[16];
+    uint32_t vmaddr;
+    uint32_t vmsize;
+    uint32_t fileoff;
+    uint32_t filesize;
+    uint32_t maxprot;
+    uint32_t initprot;
+    uint32_t nsects;
+    uint32_t flags;
+};
+
+struct macho_segment_cmd64
+{
+    char segname[16];
+    uint64_t vmaddr;
+    uint64_t vmsize;
+    uint64_t fileoff;
+    uint64_t filesize;
+    uint32_t maxprot;
+    uint32_t initprot;
+    uint32_t nsects;
+    uint32_t flags;
+};
+
+struct macho_section
+{
+    char sectname[16];
+    char segname[16];
+    uint32_t addr;
+    uint32_t size;
+    uint32_t offset;
+    uint32_t align;
+    uint32_t reloff;
+    uint32_t nreloc;
+    uint32_t flags;
+    uint32_t res1;
+    uint32_t res2;
+};
+
+struct macho_section64
+{
+    char sectname[16];
+    char segname[16];
+    uint64_t addr;
+    uint64_t size;
+    uint32_t offset;
+    uint32_t align;
+    uint32_t reloff;
+    uint32_t nreloc;
+    uint32_t flags;
+    uint32_t res1;
+    uint32_t res2;
+};
+
+int cli_scanmacho(int fd, cli_ctx *ctx)
+{
+	struct macho_hdr hdr;
+	struct macho_load_cmd load_cmd;
+	struct macho_segment_cmd segment_cmd;
+	struct macho_segment_cmd64 segment_cmd64;
+	struct macho_section section;
+	struct macho_section64 section64;
+	unsigned int i, j, sect = 0, conv, m64, nsects, vaddr, vsize, offset;
+	char name[16];
+
+    if(read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
+	cli_dbgmsg("cli_scanmacho: Can't read header\n");
+	return CL_EFORMAT;
+    }
+
+    if(hdr.magic == 0xfeedface) {
+	conv = 0;
+	m64 = 0;
+    } else if(hdr.magic == 0xcefaedfe) {
+	conv = 1;
+	m64 = 0;
+    } else if(hdr.magic == 0xfeedfacf) {
+	conv = 0;
+	m64 = 1;
+    } else if(hdr.magic == 0xcffaedfe) {
+	conv = 1;
+	m64 = 1;
+    } else {
+	cli_dbgmsg("cli_scanmacho: Incorrect magic\n");
+	return CL_EFORMAT;
+    }
+
+    switch(EC32(hdr.cpu_type, conv)) {
+	case 7:
+	    cli_dbgmsg("MACHO: CPU Type: Intel 32-bit\n");
+	    break;
+	case 7 | 0x1000000:
+	    cli_dbgmsg("MACHO: CPU Type: Intel 64-bit\n");
+	    break;
+	case 12:
+	    cli_dbgmsg("MACHO: CPU Type: ARM\n");
+	    break;
+	case 14:
+	    cli_dbgmsg("MACHO: CPU Type: SPARC\n");
+	    break;
+	case 18:
+	    cli_dbgmsg("MACHO: CPU Type: POWERPC 32-bit\n");
+	    break;
+	case 18 | 0x1000000:
+	    cli_dbgmsg("MACHO: CPU Type: POWERPC 64-bit\n");
+	    break;
+	default:
+	    cli_dbgmsg("MACHO: CPU Type: ** UNKNOWN ** (%u)\n", EC32(hdr.cpu_type, conv));
+	    break;
+    }
+
+    switch(EC32(hdr.filetype, conv)) {
+	case 0x1: /* MH_OBJECT */
+	    cli_dbgmsg("MACHO: Filetype: Relocatable object file\n");
+	    break;
+	case 0x2: /* MH_EXECUTE */
+	    cli_dbgmsg("MACHO: Filetype: Executable\n");
+	    break;
+	case 0x3: /* MH_FVMLIB */
+	    cli_dbgmsg("MACHO: Filetype: Fixed VM shared library file\n");
+	    break;
+	case 0x4: /* MH_CORE */
+	    cli_dbgmsg("MACHO: Filetype: Core file\n");
+	    break;
+	case 0x5: /* MH_PRELOAD */
+	    cli_dbgmsg("MACHO: Filetype: Preloaded executable file\n");
+	    break;
+	case 0x6: /* MH_DYLIB */
+	    cli_dbgmsg("MACHO: Filetype: Dynamically bound shared library\n");
+	    break;
+	case 0x7: /* MH_DYLINKER */
+	    cli_dbgmsg("MACHO: Filetype: Dynamic link editor\n");
+	    break;
+	case 0x8: /* MH_BUNDLE */
+	    cli_dbgmsg("MACHO: Filetype: Dynamically bound bundle file\n");
+	    break;
+	case 0x9: /* MH_DYLIB_STUB */
+	    cli_dbgmsg("MACHO: Filetype: Shared library stub for static\n");
+	    break;
+	default:
+	    cli_dbgmsg("MACHO: Filetype: ** UNKNOWN ** (0x%x)\n", EC32(hdr.filetype, conv));
+    }
+
+    cli_dbgmsg("MACHO: Number of load commands: %u\n", EC32(hdr.ncmds, conv));
+    cli_dbgmsg("MACHO: Size of load commands: %u\n", EC32(hdr.sizeofcmds, conv));
+
+    if((m64 && EC32(load_cmd.cmdsize, conv) % 8) || (!m64 && EC32(load_cmd.cmdsize, conv) % 4)) {
+	cli_dbgmsg("cli_scanmacho: Invalid command size (%u)\n", EC32(load_cmd.cmdsize, conv));
+        if(DETECT_BROKEN) {
+	    if(ctx->virname)
+		*ctx->virname = "Broken.Executable";
+	    return cli_checkfp(fd, ctx) ? CL_CLEAN : CL_VIRUS;
+        }
+	return CL_EFORMAT;
+    }
+
+    if(m64)
+	lseek(fd, 4, SEEK_CUR);
+
+    for(i = 0; i < EC32(hdr.ncmds, conv); i++) {
+	if(read(fd, &load_cmd, sizeof(load_cmd)) != sizeof(load_cmd)) {
+	    cli_dbgmsg("cli_scanmacho: Can't read load command\n");
+	    if(DETECT_BROKEN) {
+		if(ctx->virname)
+		    *ctx->virname = "Broken.Executable";
+		return cli_checkfp(fd, ctx) ? CL_CLEAN : CL_VIRUS;
+	    }
+	    return CL_EFORMAT;
+	}
+
+	if((m64 && EC32(load_cmd.cmd, conv) == 0x19) || (!m64 && EC32(load_cmd.cmd, conv) == 0x01)) { /* LC_SEGMENT */
+	    if(m64) {
+		if(read(fd, &segment_cmd64, sizeof(segment_cmd64)) != sizeof(segment_cmd64)) {
+		    cli_dbgmsg("cli_scanmacho: Can't read segment command\n");
+		    if(DETECT_BROKEN) {
+			if(ctx->virname)
+			    *ctx->virname = "Broken.Executable";
+			return cli_checkfp(fd, ctx) ? CL_CLEAN : CL_VIRUS;
+		    }
+		    return CL_EFORMAT;
+		}
+		nsects = EC32(segment_cmd64.nsects, conv);
+		strncpy(name, segment_cmd64.segname, 16);
+	    } else {
+		if(read(fd, &segment_cmd, sizeof(segment_cmd)) != sizeof(segment_cmd)) {
+		    cli_dbgmsg("cli_scanmacho: Can't read segment command\n");
+		    if(DETECT_BROKEN) {
+			if(ctx->virname)
+			    *ctx->virname = "Broken.Executable";
+			return cli_checkfp(fd, ctx) ? CL_CLEAN : CL_VIRUS;
+		    }
+		    return CL_EFORMAT;
+		}
+		nsects = EC32(segment_cmd.nsects, conv);
+		strncpy(name, segment_cmd.segname, 16);
+	    }
+	    name[15] = 0;
+	    cli_dbgmsg("MACHO: Segment name: %s\n", name);
+	    cli_dbgmsg("MACHO: Number of sections: %u\n", nsects);
+	    for(j = 0; j < nsects; j++) {
+		if(m64) {
+		    if(read(fd, &section64, sizeof(section64)) != sizeof(section64)) {
+			cli_dbgmsg("cli_scanmacho: Can't read section\n");
+			if(DETECT_BROKEN) {
+			    if(ctx->virname)
+				*ctx->virname = "Broken.Executable";
+			    return cli_checkfp(fd, ctx) ? CL_CLEAN : CL_VIRUS;
+			}
+			return CL_EFORMAT;
+		    }
+		    vaddr = EC64(section64.addr, conv);
+		    vsize = EC64(section64.size, conv);
+		    offset = EC32(section64.offset, conv);
+		    strncpy(name, section64.sectname, 16);
+		} else {
+		    if(read(fd, &section, sizeof(section)) != sizeof(section)) {
+			cli_dbgmsg("cli_scanmacho: Can't read section\n");
+			if(DETECT_BROKEN) {
+			    if(ctx->virname)
+				*ctx->virname = "Broken.Executable";
+			    return cli_checkfp(fd, ctx) ? CL_CLEAN : CL_VIRUS;
+			}
+			return CL_EFORMAT;
+		    }
+		    vaddr = EC32(section.addr, conv);
+		    vsize = EC32(section.size, conv);
+		    offset = EC32(section.offset, conv);
+		    strncpy(name, section.sectname, 16);
+		}
+		name[15] = 0;
+		cli_dbgmsg("MACHO: --- Section %u ---\n", sect);
+		cli_dbgmsg("MACHO: Name: %s\n", name);
+		cli_dbgmsg("MACHO: Virtual address: 0x%x\n", vaddr);
+		cli_dbgmsg("MACHO: Virtual size: %u\n", vsize);
+		if(offset)
+		    cli_dbgmsg("MACHO: File offset: %u\n", offset);
+		sect++;
+	    }
+	    cli_dbgmsg("MACHO: ------------------\n");
+	} else {
+	    if(EC32(load_cmd.cmdsize, conv) > sizeof(load_cmd))
+		lseek(fd, EC32(load_cmd.cmdsize, conv) - sizeof(load_cmd), SEEK_CUR);
+	}
+    }
+
+    return CL_SUCCESS;
+}
+
+int cli_machoheader(int fd, struct cli_exe_info *elfinfo)
+{
+	struct macho_hdr hdr;
+	struct macho_load_cmd load_cmd;
+	struct macho_segment_cmd segment_cmd;
+	struct macho_segment_cmd64 segment_cmd64;
+	struct macho_section section;
+	struct macho_section64 section64;
+	unsigned int i, j, sect = 0, conv, m64, nsects, vaddr, vsize, offset;
+
+    cli_dbgmsg("in cli_machoheader()\n");
+
+    if(read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
+	cli_dbgmsg("cli_scanmacho: Can't read header\n");
+	return -1;
+    }
+
+    if(hdr.magic == 0xfeedface) {
+	conv = 0;
+	m64 = 0;
+    } else if(hdr.magic == 0xcefaedfe) {
+	conv = 1;
+	m64 = 0;
+    } else if(hdr.magic == 0xfeedfacf) {
+	conv = 0;
+	m64 = 1;
+    } else if(hdr.magic == 0xcffaedfe) {
+	conv = 1;
+	m64 = 1;
+    } else {
+	cli_dbgmsg("cli_scanmacho: Incorrect magic\n");
+	return CL_EFORMAT;
+    }
+
+    if((m64 && EC32(load_cmd.cmdsize, conv) % 8) || (!m64 && EC32(load_cmd.cmdsize, conv) % 4)) {
+	cli_dbgmsg("cli_scanmacho: Invalid command size (%u)\n", EC32(load_cmd.cmdsize, conv));
+	return -1;
+    }
+
+    if(m64)
+	lseek(fd, 4, SEEK_CUR);
+
+    for(i = 0; i < EC32(hdr.ncmds, conv); i++) {
+	if(read(fd, &load_cmd, sizeof(load_cmd)) != sizeof(load_cmd)) {
+	    cli_dbgmsg("cli_scanmacho: Can't read load command\n");
+	    return -1;
+	}
+
+	if((m64 && EC32(load_cmd.cmd, conv) == 0x19) || (!m64 && EC32(load_cmd.cmd, conv) == 0x01)) { /* LC_SEGMENT */
+	    if(m64) {
+		if(read(fd, &segment_cmd64, sizeof(segment_cmd64)) != sizeof(segment_cmd64)) {
+		    cli_dbgmsg("cli_scanmacho: Can't read segment command\n");
+		    return -1;
+		}
+		nsects = EC32(segment_cmd64.nsects, conv);
+	    } else {
+		if(read(fd, &segment_cmd, sizeof(segment_cmd)) != sizeof(segment_cmd)) {
+		    cli_dbgmsg("cli_scanmacho: Can't read segment command\n");
+		    return -1;
+		}
+		nsects = EC32(segment_cmd.nsects, conv);
+	    }
+	    for(j = 0; j < nsects; j++) {
+		if(m64) {
+		    if(read(fd, &section64, sizeof(section64)) != sizeof(section64)) {
+			cli_dbgmsg("cli_scanmacho: Can't read section\n");
+			return -1;
+		    }
+		    vaddr = EC64(section64.addr, conv);
+		    vsize = EC64(section64.size, conv);
+		    offset = EC32(section64.offset, conv);
+		} else {
+		    if(read(fd, &section, sizeof(section)) != sizeof(section)) {
+			cli_dbgmsg("cli_scanmacho: Can't read section\n");
+			return -1;
+		    }
+		    vaddr = EC32(section.addr, conv);
+		    vsize = EC32(section.size, conv);
+		    offset = EC32(section.offset, conv);
+		}
+		sect++;
+	    }
+	} else {
+	    if(EC32(load_cmd.cmdsize, conv) > sizeof(load_cmd))
+		lseek(fd, EC32(load_cmd.cmdsize, conv) - sizeof(load_cmd), SEEK_CUR);
+	}
+    }
+
+    return 0;
+}
diff --git a/libclamav/cpio.h b/libclamav/macho.h
similarity index 81%
copy from libclamav/cpio.h
copy to libclamav/macho.h
index abfc66b..c8553d0 100644
--- a/libclamav/cpio.h
+++ b/libclamav/macho.h
@@ -18,13 +18,13 @@
  *  MA 02110-1301, USA.
  */
 
-#ifndef __CPIO_H
-#define __CPIO_H
+#ifndef __MACHO_H
+#define __MACHO_H
 
 #include "others.h"
+#include "execs.h"
 
-int cli_scancpio_old(int fd, cli_ctx *ctx);
-int cli_scancpio_odc(int fd, cli_ctx *ctx);
-int cli_scancpio_newc(int fd, cli_ctx *ctx, int crc);
+int cli_scanmacho(int fd, cli_ctx *ctx);
+int cli_machoheader(int fd, struct cli_exe_info *elfinfo);
 
 #endif

-- 
Debian repository for ClamAV



More information about the Pkg-clamav-commits mailing list