Browse code

Decode and scan OLE objects embedded in MS Office documents.

git-svn: trunk@1480

Trog authored on 2005/04/15 03:42:13
Showing 4 changed files
... ...
@@ -1,3 +1,7 @@
1
+Thu Apr 14 19:39:49 BST 2005 (trog)
2
+  * libclamav/scanners.c, libclamav/vba_extract.[ch]:
3
+	Decode and scan OLE objects embedded in MS Office documents.
4
+
1 5
 Thu Apr 14 14:35:37 BST 2005 (trog)
2 6
 -----------------------------------
3 7
   * libclamav/scanners.c: Activate new RAR code.
... ...
@@ -822,7 +822,7 @@ static int cli_scandir(const char *dirname, const char **virname, long int *scan
822 822
 
823 823
 static int cli_vba_scandir(const char *dirname, 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)
824 824
 {
825
-	int ret = CL_CLEAN, i, fd, data_len;
825
+	int ret = CL_CLEAN, i, fd, ofd, data_len;
826 826
 	vba_project_t *vba_project;
827 827
 	DIR *dd;
828 828
 	struct dirent *dent;
... ...
@@ -926,6 +926,22 @@ static int cli_vba_scandir(const char *dirname, const char **virname, long int *
926 926
     if(ret != CL_CLEAN)
927 927
     	return ret;
928 928
 
929
+    /* Check directory for embedded OLE objects */
930
+    fullname = (char *) cli_malloc(strlen(dirname) + 16);
931
+    sprintf(fullname, "%s/_1_Ole10Native", dirname);
932
+    fd = open(fullname, O_RDONLY);
933
+    free(fullname);
934
+    if (fd >= 0) {
935
+    	ofd = cli_decode_ole_object(fd, dirname);
936
+	if (ofd >= 0) {
937
+		ret = cli_scandesc(ofd, virname, scanned, root, 0, 0);
938
+		close(ofd);
939
+	}
940
+	close(fd);
941
+	if(ret != CL_CLEAN)
942
+	    return ret;
943
+    }
944
+
929 945
     if((dd = opendir(dirname)) != NULL) {
930 946
 #ifdef HAVE_READDIR_R_3
931 947
 	while(!readdir_r(dd, &result.d, &dent) && dent) {
... ...
@@ -42,6 +42,10 @@
42 42
 #define FALSE (0)
43 43
 #define TRUE (1)
44 44
 
45
+#ifndef MIN
46
+#define MIN(a, b)  (((a) < (b)) ? (a) : (b))
47
+#endif
48
+
45 49
 typedef struct vba_version_tag {
46 50
 	unsigned char signature[4];
47 51
 	const char *name;
... ...
@@ -685,12 +689,97 @@ unsigned char *vba_decompress(int fd, uint32_t offset, int *size)
685 685
 
686 686
 }
687 687
 
688
+static uint32_t ole_copy_file_data(int ifd, int ofd, uint32_t len)
689
+{
690
+        unsigned char data[8192];
691
+        unsigned int count, rem;
692
+        unsigned int todo;
693
+
694
+        rem = len;
695
+
696
+        while (rem > 0) {
697
+                todo = MIN(8192, rem);
698
+                count = cli_readn(ifd, data, todo);
699
+                if (count != todo) {
700
+                        return len-rem;
701
+                }
702
+                if (cli_writen(ofd, data, count) != count) {
703
+                        return len-rem-count;
704
+                }
705
+                rem -= count;
706
+        }
707
+        return len;
708
+}
709
+
710
+int cli_decode_ole_object(int fd, const char *dir)
711
+{
712
+	int ofd;
713
+	struct stat statbuf;
714
+	char ch, *fullname;
715
+	uint32_t object_size;
716
+
717
+	if (fstat(fd, &statbuf) == -1) {
718
+		return -1;
719
+	}
720
+	
721
+	if (cli_readn(fd, &object_size, 4) != 4) {
722
+		return -1;
723
+	}
724
+	object_size = vba_endian_convert_32(object_size, FALSE);
725
+
726
+	if ((statbuf.st_size -  object_size) >= 4) {
727
+		/* Probably the OLE type id */
728
+		if (lseek(fd, 2, SEEK_CUR) == -1) {
729
+			return -1;
730
+		}
731
+		
732
+		/* Skip attachment name */
733
+		do {
734
+			if (cli_readn(fd, &ch, 1) != 1) {
735
+				return -1;
736
+			}
737
+		} while (ch);
738
+		
739
+		/* Skip attachment full path */
740
+		do {
741
+			if (cli_readn(fd, &ch, 1) != 1) {
742
+				return -1;
743
+			}
744
+		} while (ch);
745
+		
746
+		/* Skip unknown data */
747
+		if (lseek(fd, 8, SEEK_CUR) == -1) {
748
+			return -1;
749
+		}
750
+		
751
+		/* Skip attachment full path */
752
+		do {
753
+			if (cli_readn(fd, &ch, 1) != 1) {
754
+				return -1;
755
+			}
756
+		} while (ch);
757
+		
758
+		if (cli_readn(fd, &object_size, 4) != 4) {
759
+			return -1;
760
+		}
761
+		object_size = vba_endian_convert_32(object_size, FALSE);
762
+	}
763
+	fullname = cli_malloc(strlen(dir) + 18);
764
+	sprintf(fullname, "%s/_clam_ole_object", dir);
765
+	ofd = open(fullname, O_WRONLY|O_CREAT|O_TRUNC, 0600);
766
+	free(fullname);
767
+        if (ofd < 0) {
768
+		return -1;
769
+	}
770
+	ole_copy_file_data(fd, ofd, object_size);
771
+	lseek(0, ofd, SEEK_SET);
772
+	return ofd;
773
+}
774
+
688 775
 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
689 776
 /* Code to extract Power Point Embedded OLE2 Objects		     */
690 777
 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
691 778
 
692
-#define MIN(a, b)  (((a) < (b)) ? (a) : (b))
693
-
694 779
 typedef struct atom_header_tag {
695 780
 	off_t foffset;
696 781
 	uint16_t ver_inst;
... ...
@@ -36,6 +36,7 @@ typedef struct vba_project_tag {
36 36
 
37 37
 vba_project_t *vba56_dir_read(const char *dir);
38 38
 unsigned char *vba_decompress(int fd, uint32_t offset, int *size);
39
+int cli_decode_ole_object(int fd, const char *dir);
39 40
 
40 41
 char *ppt_vba_read(const char *dir);
41 42