Browse code

Word6 macro extraction code (not yet activated)

git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@525 77e5149b-7576-45b1-b177-96237e5ba77b

Trog authored on 2004/04/27 20:42:53
Showing 3 changed files
... ...
@@ -1,6 +1,10 @@
1
+Tue Apr 27 12:42:14 BST 2004 (trog)
2
+-----------------------------------
3
+ * libclamav/vba_extract.[ch]: Word6 macro extraction code (not yet activated)
4
+
1 5
 Mon Apr 26 11:51:28 BST 2004 (trog)
2 6
 -----------------------------------
3
- libclamav/ole2_extract.c: Better support for non-standard OLE2 archives
7
+ * libclamav/ole2_extract.c: Better support for non-standard OLE2 archives
4 8
 
5 9
 Sun Apr 25 13:58:35 BST 2004 (njh)
6 10
 ----------------------------------
... ...
@@ -620,3 +620,719 @@ unsigned char *vba_decompress(int fd, uint32_t offset, int *size)
620 620
 	return result.data;
621 621
 
622 622
 }
623
+
624
+/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
625
+/* Code to extract Word6 macros
626
+/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
627
+
628
+typedef struct mso_fib_tag {
629
+	uint16_t magic;
630
+	uint16_t version;
631
+	uint16_t product;
632
+	uint16_t lid;
633
+	uint16_t next;
634
+	uint16_t status;
635
+	/* block of 268 bytes - ignore */
636
+	uint32_t macro_offset;
637
+	uint32_t macro_len;
638
+} mso_fib_t;
639
+
640
+typedef struct macro_entry_tag {
641
+	unsigned char version;
642
+	unsigned char key;
643
+	uint16_t intname_i;
644
+	uint16_t extname_i;
645
+	uint16_t xname_i;
646
+	uint32_t unknown;
647
+	uint32_t len;
648
+	uint32_t state;
649
+	uint32_t offset;
650
+} macro_entry_t;
651
+
652
+typedef struct macro_info_tag {
653
+	uint16_t count;
654
+	struct macro_entry_tag *macro_entry;
655
+} macro_info_t;
656
+
657
+typedef struct macro_extname_tag {
658
+	uint8_t length;
659
+	unsigned char *extname;
660
+	uint16_t numref;
661
+} macro_extname_t;
662
+
663
+typedef struct macro_extnames_tag {
664
+	uint16_t count;
665
+	struct macro_extname_tag *macro_extname;
666
+} macro_extnames_t;
667
+
668
+typedef struct macro_intnames_tag {
669
+	uint16_t count;
670
+	struct macro_intname_tag *macro_intname;
671
+} macro_intnames_t;
672
+
673
+typedef struct macro_intname_tag {
674
+	uint16_t id;
675
+	uint8_t length;
676
+	unsigned char *intname;
677
+} macro_intname_t;
678
+
679
+typedef struct menu_entry_tag {
680
+	uint16_t context;
681
+	uint16_t menu;
682
+	uint16_t extname_i;
683
+	uint16_t unknown;
684
+	uint16_t intname_i;
685
+	uint16_t pos;
686
+} menu_entry_t;
687
+
688
+typedef struct menu_info_tag {
689
+	uint16_t count;
690
+	struct menu_entry_tag *menu_entry;
691
+} menu_info_t;
692
+
693
+typedef struct mac_token_tag {
694
+	unsigned char token;
695
+	unsigned char *str;
696
+} mac_token_t;
697
+
698
+typedef struct mac_token2_tag {
699
+	uint16_t token;
700
+	unsigned char *str;
701
+
702
+} mac_token2_t;
703
+
704
+static void wm_print_fib(mso_fib_t *fib)
705
+{
706
+	cli_dbgmsg("magic: 0x%.4x\n", fib->magic);
707
+	cli_dbgmsg("version: 0x%.4x\n", fib->version);
708
+	cli_dbgmsg("product: 0x%.4x\n", fib->product);
709
+	cli_dbgmsg("lid: 0x%.4x\n", fib->lid);
710
+	cli_dbgmsg("macro offset: 0x%.4x\n", fib->macro_offset);
711
+	cli_dbgmsg("macro len: 0x%.4x\n\n", fib->macro_len);
712
+}
713
+	
714
+static int wm_read_fib(int fd, mso_fib_t *fib)
715
+{
716
+	if (cli_readn(fd, &fib->magic, 2) != 2) {
717
+		printf("read wm_fib failed\n");
718
+		return FALSE;
719
+	}
720
+	if (cli_readn(fd, &fib->version, 2) != 2) {
721
+		printf("read wm_fib failed\n");
722
+		return FALSE;
723
+	}
724
+	if (cli_readn(fd, &fib->product, 2) != 2) {
725
+		printf("read wm_fib failed\n");
726
+		return FALSE;
727
+	}
728
+	if (cli_readn(fd, &fib->lid, 2) != 2) {
729
+		printf("read wm_fib failed\n");
730
+		return FALSE;
731
+	}	
732
+	if (cli_readn(fd, &fib->next, 2) != 2) {
733
+		printf("read wm_fib failed\n");
734
+		return FALSE;
735
+	}
736
+	if (cli_readn(fd, &fib->status, 2) != 2) {
737
+		printf("read wm_fib failed\n");
738
+		return FALSE;
739
+	}
740
+	
741
+	/* don't need the information is this block, so seek forward */
742
+	if (lseek(fd, 0x118, SEEK_SET) != 0x118) {
743
+		printf("lseek wm_fib failed\n");
744
+		return FALSE;
745
+	}
746
+	
747
+	if (cli_readn(fd, &fib->macro_offset, 4) != 4) {
748
+		printf("read wm_fib failed\n");
749
+		return FALSE;
750
+	}
751
+	if (cli_readn(fd, &fib->macro_len, 4) != 4) {
752
+		printf("read wm_fib failed\n");
753
+		return FALSE;
754
+	}
755
+	fib->magic = vba_endian_convert_16(fib->magic, FALSE);
756
+	fib->version = vba_endian_convert_16(fib->version, FALSE);
757
+	fib->product = vba_endian_convert_16(fib->product, FALSE);
758
+	fib->lid = vba_endian_convert_16(fib->lid, FALSE);
759
+	fib->next = vba_endian_convert_16(fib->next, FALSE);
760
+	fib->status = vba_endian_convert_16(fib->status, FALSE);
761
+	fib->macro_offset = vba_endian_convert_32(fib->macro_offset, FALSE);
762
+	fib->macro_len = vba_endian_convert_32(fib->macro_len, FALSE);
763
+	
764
+	return TRUE;
765
+}
766
+
767
+static int wm_read_macro_entry(int fd, macro_entry_t *macro_entry)
768
+{
769
+	if (cli_readn(fd, &macro_entry->version, 1) != 1) {
770
+		printf("read macro_entry failed\n");
771
+		return FALSE;
772
+	}
773
+	if (cli_readn(fd, &macro_entry->key, 1) != 1) {
774
+		printf("read macro_entry failed\n");
775
+		return FALSE;
776
+	}
777
+	if (cli_readn(fd, &macro_entry->intname_i, 2) != 2) {
778
+		printf("read macro_entry failed\n");
779
+		return FALSE;
780
+	}	
781
+	if (cli_readn(fd, &macro_entry->extname_i, 2) != 2) {
782
+		printf("read macro_entry failed\n");
783
+		return FALSE;
784
+	}
785
+	if (cli_readn(fd, &macro_entry->xname_i, 2) != 2) {
786
+		printf("read macro_entry failed\n");
787
+		return FALSE;
788
+	}
789
+	if (cli_readn(fd, &macro_entry->unknown, 4) != 4) {
790
+		printf("read macro_entry failed\n");
791
+		return FALSE;
792
+	}
793
+	if (cli_readn(fd, &macro_entry->len, 4) != 4) {
794
+		printf("read macro_entry failed\n");
795
+		return FALSE;
796
+	}
797
+	if (cli_readn(fd, &macro_entry->state, 4) != 4) {
798
+		printf("read macro_entry failed\n");
799
+		return FALSE;
800
+	}
801
+	if (cli_readn(fd, &macro_entry->offset, 4) != 4) {
802
+		printf("read macro_entry failed\n");
803
+		return FALSE;
804
+	}
805
+	return TRUE;
806
+}
807
+
808
+static macro_info_t *wm_read_macro_info(int fd)
809
+{
810
+	int i;
811
+	macro_info_t *macro_info;
812
+
813
+	macro_info = (macro_info_t *) cli_malloc(sizeof(macro_info_t));
814
+	if (!macro_info) {
815
+		return NULL;
816
+	}
817
+	if (cli_readn(fd, &macro_info->count, 2) != 2) {
818
+		printf("read macro_info failed\n");
819
+		return NULL;
820
+	}
821
+	
822
+	cli_dbgmsg("macro count: %d\n", macro_info->count);
823
+	macro_info->macro_entry = (macro_entry_t *)
824
+			cli_malloc(sizeof(macro_entry_t) * macro_info->count);
825
+	if (!macro_info->macro_entry) {
826
+		free(macro_info);
827
+		return NULL;
828
+	}
829
+	for (i=0 ; i < macro_info->count ; i++) {
830
+		if (!wm_read_macro_entry(fd,
831
+				&macro_info->macro_entry[i])) {
832
+			free(macro_info->macro_entry);
833
+			free(macro_info);
834
+			return NULL;
835
+		}
836
+	}
837
+	return macro_info;
838
+}
839
+
840
+static void wm_free_macro_info(macro_info_t *macro_info)
841
+{
842
+	if (macro_info) {
843
+		free(macro_info->macro_entry);
844
+		free(macro_info);
845
+	}
846
+	return;
847
+}
848
+
849
+static int wm_read_oxo3(int fd)
850
+{
851
+	uint8_t count;
852
+
853
+	if (cli_readn(fd, &count, 1) != 1) {
854
+		cli_dbgmsg("read oxo3 record1 failed\n");
855
+		return FALSE;
856
+	}
857
+	if (lseek(fd, count*14, SEEK_CUR) == -1) {
858
+		cli_dbgmsg("lseek oxo3 record1 failed\n");
859
+		return FALSE;
860
+	}
861
+	cli_dbgmsg("oxo3 records1: %d\n", count);
862
+	
863
+	if (cli_readn(fd, &count, 1) != 1) {
864
+		printf("read oxo3 record2 failed\n");
865
+		return FALSE;
866
+	}
867
+	if (count == 0) {
868
+		if (cli_readn(fd, &count, 1) != 1) {
869
+			printf("read oxo3 failed\n");
870
+			return FALSE;
871
+		}
872
+		if (count != 2) {
873
+			lseek(fd, -1, SEEK_CUR);
874
+			return TRUE;
875
+		}
876
+		if (cli_readn(fd, &count, 1) != 1) {
877
+			printf("read oxo3 failed\n");
878
+			return FALSE;
879
+		}
880
+	}
881
+	if (count > 0) {
882
+		if (lseek(fd, (count*4)+1, SEEK_CUR) == -1) {
883
+			printf("lseek oxo3 failed\n");
884
+			return FALSE;
885
+		}
886
+	}				
887
+	cli_dbgmsg("oxo3 records2: %d\n", count);
888
+	return TRUE;
889
+}
890
+
891
+static menu_info_t *wm_read_menu_info(int fd)
892
+{
893
+	int i;
894
+	menu_info_t *menu_info;
895
+	menu_entry_t *menu_entry;
896
+	
897
+	menu_info = (menu_info_t *) cli_malloc(sizeof(menu_info_t));
898
+	if (!menu_info) {
899
+		return NULL;
900
+	}
901
+	
902
+	if (cli_readn(fd, &menu_info->count, 2) != 2) {
903
+		printf("read menu_info failed\n");
904
+		free(menu_info);
905
+		return NULL;
906
+	}
907
+	printf("menu_info count: %d\n", menu_info->count);
908
+	
909
+	menu_info->menu_entry =
910
+		(menu_entry_t *) cli_malloc(sizeof(menu_entry_t) * menu_info->count);
911
+	if (!menu_info->menu_entry) {
912
+		free(menu_info);
913
+		return NULL;
914
+	}
915
+	
916
+	for (i=0 ; i < menu_info->count ; i++) {
917
+		menu_entry = &menu_info->menu_entry[i];
918
+		if (cli_readn(fd, &menu_entry->context, 2) != 2) {
919
+			goto abort;
920
+		}
921
+		if (cli_readn(fd, &menu_entry->menu, 2) != 2) {
922
+			goto abort;
923
+		}
924
+		if (cli_readn(fd, &menu_entry->extname_i, 2) != 2) {
925
+			goto abort;
926
+		}
927
+		if (cli_readn(fd, &menu_entry->unknown, 2) != 2) {
928
+			goto abort;
929
+		}
930
+		if (cli_readn(fd, &menu_entry->intname_i, 2) != 2) {
931
+			goto abort;
932
+		}
933
+		if (cli_readn(fd, &menu_entry->pos, 2) != 2) {
934
+			goto abort;
935
+		}
936
+		cli_dbgmsg("menu entry: %d.%d\n", menu_entry->menu, menu_entry->pos);
937
+	}
938
+	return menu_info;
939
+	
940
+abort:
941
+	cli_dbgmsg("read menu_entry failed\n");
942
+	free(menu_info->menu_entry);
943
+	free(menu_info);
944
+	return NULL;
945
+}
946
+
947
+static void wm_free_menu_info(menu_info_t *menu_info)
948
+{
949
+	if (menu_info) {
950
+		free(menu_info->menu_entry);
951
+		free(menu_info);
952
+	}
953
+	return;
954
+}
955
+
956
+static macro_extnames_t *wm_read_macro_extnames(int fd)
957
+{
958
+	int i, is_unicode=0;
959
+	int16_t size;
960
+	uint8_t length_tmp;
961
+	off_t offset_end;	
962
+	macro_extnames_t *macro_extnames;
963
+	macro_extname_t *macro_extname;
964
+	unsigned char *name_tmp;
965
+	
966
+	macro_extnames = (macro_extnames_t *) cli_malloc(sizeof(macro_extnames_t));
967
+	if (!macro_extnames) {
968
+		return NULL;
969
+	}
970
+	macro_extnames->count = 0;
971
+	macro_extnames->macro_extname = NULL;
972
+	
973
+	offset_end = lseek(fd, 0, SEEK_CUR);
974
+	if (cli_readn(fd, &size, 2) != 2) {
975
+		cli_dbgmsg("read macro_extnames failed\n");
976
+		free(macro_extnames);
977
+		return NULL;
978
+	}
979
+	if (size == -1) { /* Unicode flag */
980
+		is_unicode=1;
981
+		if (cli_readn(fd, &size, 2) != 2) {
982
+			printf("read macro_extnames failed\n");
983
+			free(macro_extnames);
984
+			return NULL;
985
+		}
986
+	}
987
+	cli_dbgmsg("ext names size: 0x%x\n", size);
988
+
989
+	offset_end += size;
990
+	while (lseek(fd, 0, SEEK_CUR) < offset_end) {
991
+		macro_extnames->count++;
992
+		if (macro_extnames->count > 0) {
993
+			macro_extnames->macro_extname = (macro_extname_t *)
994
+				cli_realloc(macro_extnames->macro_extname,
995
+					sizeof(macro_extname_t) * macro_extnames->count);
996
+			if (macro_extnames->macro_extname == NULL) {
997
+				free(macro_extnames);
998
+				return NULL;
999
+			}
1000
+		} else {
1001
+			macro_extnames->macro_extname =
1002
+				(macro_extname_t *) cli_malloc(sizeof(macro_extname_t));
1003
+			if (macro_extnames->macro_extname == NULL) {
1004
+				free(macro_extnames);
1005
+				return NULL;
1006
+			}
1007
+		}
1008
+		macro_extname = &macro_extnames->macro_extname[macro_extnames->count-1];
1009
+		if (is_unicode) {
1010
+			if (cli_readn(fd, &macro_extname->length, 2) != 2) {
1011
+				printf("read macro_extnames failed\n");
1012
+				return NULL;
1013
+			}
1014
+			name_tmp = (char *) cli_malloc(macro_extname->length*2);
1015
+			if (name_tmp == NULL) {
1016
+				goto abort;
1017
+			}
1018
+			if (cli_readn(fd, name_tmp, macro_extname->length*2) != 
1019
+						macro_extname->length*2) {
1020
+				printf("read macro_extnames failed\n");
1021
+				free(name_tmp);
1022
+				goto abort;
1023
+			}
1024
+			macro_extname->extname =
1025
+			get_unicode_name(name_tmp, macro_extname->length*2, FALSE);
1026
+			free(name_tmp);
1027
+		} else {
1028
+			if (cli_readn(fd, &length_tmp, 1) != 1) {
1029
+				printf("read macro_extnames failed\n");
1030
+				goto abort;
1031
+			}
1032
+			macro_extname->length = (uint16_t) length_tmp;
1033
+			macro_extname->extname = (char *) cli_malloc(macro_extname->length+1);
1034
+			if (!macro_extname->extname) {
1035
+				macro_extnames->count--;
1036
+				goto abort;
1037
+			}
1038
+			if (cli_readn(fd, macro_extname->extname, macro_extname->length) != 
1039
+						macro_extname->length) {
1040
+				printf("read macro_extnames failed\n");
1041
+				goto abort;
1042
+			}
1043
+			macro_extname->extname[macro_extname->length] = '\0';
1044
+		}
1045
+		if (cli_readn(fd, &macro_extname->numref, 2) != 2) {
1046
+			printf("read macro_extnames failed\n");
1047
+			return NULL;
1048
+		}		
1049
+		cli_dbgmsg("ext name: %s\n", macro_extname->extname);
1050
+	}
1051
+	return macro_extnames;
1052
+	
1053
+abort:
1054
+	if (macro_extnames->macro_extname != NULL) {
1055
+		for (i=0 ; i < macro_extnames->count ; i++) {
1056
+			free(macro_extnames->macro_extname[i].extname);
1057
+		}
1058
+		free(macro_extname);
1059
+	}
1060
+	free(macro_extnames);
1061
+	return NULL;
1062
+}
1063
+
1064
+static void wm_free_extnames(macro_extnames_t *macro_extnames)
1065
+{
1066
+	int i;
1067
+	
1068
+	if (macro_extnames) {
1069
+		for (i=0 ; i < macro_extnames->count ; i++) {
1070
+			free(macro_extnames->macro_extname[i].extname);
1071
+		}
1072
+		free(macro_extnames->macro_extname);
1073
+		free(macro_extnames);
1074
+	}
1075
+	return;
1076
+}
1077
+
1078
+static macro_intnames_t *wm_read_macro_intnames(int fd)
1079
+{
1080
+	int i;
1081
+	macro_intnames_t *macro_intnames;
1082
+	macro_intname_t *macro_intname;
1083
+	uint16_t junk;
1084
+	
1085
+	macro_intnames = (macro_intnames_t *) cli_malloc(sizeof(macro_intnames_t));
1086
+	if (!macro_intnames) {
1087
+		return NULL;
1088
+	}
1089
+	
1090
+	if (cli_readn(fd, &macro_intnames->count, 2) != 2) {
1091
+		printf("read macro_intnames failed\n");
1092
+		return NULL;
1093
+	}
1094
+	cli_dbgmsg("int names count: %d\n", macro_intnames->count);
1095
+	
1096
+	macro_intnames->macro_intname =
1097
+		(macro_intname_t *) cli_malloc(sizeof(macro_intname_t) * macro_intnames->count);
1098
+	if (!macro_intnames->macro_intname) {
1099
+		free(macro_intnames);
1100
+		return NULL;
1101
+	}
1102
+	for (i=0 ; i < macro_intnames->count ; i++) {
1103
+		macro_intname = &macro_intnames->macro_intname[i];
1104
+		if (cli_readn(fd, &macro_intname->id, 2) != 2) {
1105
+			printf("read macro_intnames failed\n");
1106
+			macro_intnames->count = i;
1107
+			goto abort;
1108
+		}		
1109
+		if (cli_readn(fd, &macro_intname->length, 1) != 1) {
1110
+			printf("read macro_intnames failed\n");
1111
+			macro_intnames->count = i;
1112
+			goto abort;;
1113
+		}	
1114
+		macro_intname->intname = (char *) cli_malloc(macro_intname->length+1);
1115
+		if (!macro_intname->intname) {
1116
+			macro_intnames->count = i;
1117
+			goto abort;
1118
+		}
1119
+		if (cli_readn(fd, macro_intname->intname, macro_intname->length) != macro_intname->length) {
1120
+			printf("read macro_intnames failed\n");
1121
+			macro_intnames->count = i+1;
1122
+			goto abort;
1123
+		}
1124
+		macro_intname->intname[macro_intname->length] = '\0';
1125
+		if (cli_readn(fd, &junk, 1) != 1) {
1126
+			printf("read macro_intnames failed\n");
1127
+			macro_intnames->count = i+1;
1128
+			goto abort;
1129
+		}
1130
+		printf ("int name: %s\n", macro_intname->intname);
1131
+	}
1132
+	return macro_intnames;
1133
+abort:
1134
+	for (i=0 ; i < macro_intnames->count ; i++) {
1135
+		free(macro_intnames->macro_intname[i].intname);
1136
+	}
1137
+	free(macro_intnames->macro_intname);
1138
+	free(macro_intnames);
1139
+	return NULL;
1140
+}
1141
+
1142
+static void wm_free_intnames(macro_intnames_t *macro_intnames)
1143
+{
1144
+	int i;
1145
+	
1146
+	if (macro_intnames) {
1147
+		for (i=0 ; i < macro_intnames->count ; i++) {
1148
+			free(macro_intnames->macro_intname[i].intname);
1149
+		}
1150
+		free(macro_intnames->macro_intname);
1151
+		free(macro_intnames);
1152
+	}
1153
+	return;
1154
+}
1155
+
1156
+vba_project_t *wm_dir_read(const char *dir)
1157
+{
1158
+	int fd, done=FALSE, i;
1159
+	mso_fib_t fib;
1160
+	off_t end_offset;
1161
+	unsigned char start_id, info_id;
1162
+	macro_info_t *macro_info=NULL;
1163
+	menu_info_t *menu_info=NULL;
1164
+	macro_extnames_t *macro_extnames=NULL;
1165
+	macro_intnames_t *macro_intnames=NULL;
1166
+	vba_project_t *vba_project=NULL;
1167
+	char *fullname;
1168
+	
1169
+	fullname = (char *) cli_malloc(strlen(dir) + 15);
1170
+	sprintf(fullname, "%s/WordDocument", dir);
1171
+	fd = open(fullname, O_RDONLY);
1172
+	free(fullname);
1173
+	if (fd == -1) {
1174
+		cli_dbgmsg("Open WordDocument failed\n");
1175
+		return NULL;
1176
+	}
1177
+	
1178
+	if (!wm_read_fib(fd, &fib)) {
1179
+		return NULL;
1180
+	}
1181
+	wm_print_fib(&fib);
1182
+	
1183
+	if (lseek(fd, fib.macro_offset, SEEK_SET) != fib.macro_offset) {
1184
+		cli_dbgmsg("lseek macro_offset failed\n");
1185
+		return NULL;
1186
+	}
1187
+	
1188
+	end_offset = fib.macro_offset + fib.macro_len;
1189
+	
1190
+	if (cli_readn(fd, &start_id, 1) != 1) {
1191
+		printf("read start_id failed\n");
1192
+		return NULL;
1193
+	}
1194
+	cli_dbgmsg("start_id: %d\n", start_id);
1195
+	
1196
+	while ((lseek(fd, 0, SEEK_CUR) < end_offset) && !done) {
1197
+		if (cli_readn(fd, &info_id, 1) != 1) {
1198
+			printf("read macro_info failed\n");
1199
+			return NULL;
1200
+		}
1201
+		switch (info_id) {
1202
+			case 0x01:
1203
+				macro_info = wm_read_macro_info(fd);
1204
+				if (macro_info == NULL) {
1205
+					done = TRUE;
1206
+				}
1207
+				break;
1208
+			case 0x03:
1209
+				if (!wm_read_oxo3(fd)) {
1210
+					done = TRUE;
1211
+				}
1212
+				break;
1213
+			case 0x05:
1214
+				menu_info = wm_read_menu_info(fd);
1215
+				if (menu_info == NULL) {
1216
+					done = TRUE;
1217
+				}
1218
+				break;
1219
+			case 0x10:
1220
+				macro_extnames = wm_read_macro_extnames(fd);
1221
+				if (macro_extnames == NULL) {
1222
+					done = TRUE;
1223
+				}
1224
+				break;
1225
+			case 0x11:
1226
+				macro_intnames = wm_read_macro_intnames(fd);
1227
+				if (macro_intnames == NULL) {
1228
+					done = TRUE;
1229
+				}				
1230
+				break;
1231
+			case 0x12:
1232
+				/* No sure about these, always seems to
1233
+				come after the macros though, so finish
1234
+				*/
1235
+				done = 1;
1236
+				break;
1237
+			case 0x40:
1238
+				/* end marker */
1239
+				done = 1;
1240
+				break;
1241
+			default:
1242
+				cli_dbgmsg("\nunknown type: 0x%x\n", info_id);
1243
+				done = 1;
1244
+		}
1245
+	}
1246
+	
1247
+	if (macro_info) {
1248
+		vba_project = (vba_project_t *) cli_malloc(sizeof(struct vba_project_tag));
1249
+		if (!vba_project) {
1250
+			goto abort;
1251
+		}
1252
+		vba_project->name = (char **) cli_malloc(sizeof(char *) *macro_info->count);
1253
+		if (!vba_project->name) {
1254
+			free(vba_project);
1255
+			vba_project = NULL;
1256
+			goto abort;
1257
+		}
1258
+		vba_project->dir = strdup(dir);
1259
+		vba_project->offset = (uint32_t *) cli_malloc(sizeof(uint32_t) *
1260
+					macro_info->count);
1261
+		if (!vba_project->offset) {
1262
+			free(vba_project->name);
1263
+			free(vba_project->dir);
1264
+			free(vba_project);
1265
+			vba_project = NULL;
1266
+			goto abort;
1267
+		}
1268
+		vba_project->length = (uint32_t *) cli_malloc(sizeof(uint32_t) *
1269
+					macro_info->count);
1270
+		if (!vba_project->length) {
1271
+			free(vba_project->offset);
1272
+			free(vba_project->name);
1273
+			free(vba_project->dir);
1274
+			free(vba_project);
1275
+			vba_project = NULL;
1276
+			goto abort;
1277
+		}
1278
+		vba_project->key = (unsigned char *) cli_malloc(sizeof(unsigned char) *
1279
+					macro_info->count);
1280
+		if (!vba_project->key) {
1281
+			free(vba_project->length);
1282
+			free(vba_project->offset);
1283
+			free(vba_project->name);
1284
+			free(vba_project->dir);
1285
+			free(vba_project);
1286
+			vba_project = NULL;
1287
+			goto abort;
1288
+		}
1289
+		vba_project->count = macro_info->count;
1290
+		for (i=0 ; i < macro_info->count ; i++) {
1291
+			vba_project->name[i] = strdup("WordDocument");
1292
+			vba_project->offset[i] = macro_info->macro_entry[i].offset;
1293
+			vba_project->length[i] = macro_info->macro_entry[i].len;
1294
+			vba_project->key[i] = macro_info->macro_entry[i].key;
1295
+		}
1296
+	}
1297
+	/* Fall through */
1298
+abort:
1299
+	if (macro_info) {
1300
+		wm_free_macro_info(macro_info);
1301
+	}
1302
+	if (menu_info) {
1303
+		wm_free_menu_info(menu_info);
1304
+	}
1305
+	if (macro_extnames) {
1306
+		wm_free_extnames(macro_extnames);
1307
+	}
1308
+	if (macro_intnames) {
1309
+		wm_free_intnames(macro_intnames);
1310
+	}
1311
+	return vba_project;
1312
+}
1313
+
1314
+unsigned char *wm_decrypt_macro(int fd, uint32_t offset, uint32_t len,
1315
+					unsigned char key)
1316
+{
1317
+	unsigned char *buff;
1318
+	uint32_t i;
1319
+	
1320
+	if (lseek(fd, offset, SEEK_SET) != offset) {
1321
+		return NULL;
1322
+	}
1323
+	buff = (unsigned char *) cli_malloc(len);
1324
+	if (!buff) {
1325
+		return NULL;
1326
+	}
1327
+
1328
+	if (cli_readn(fd, buff, len) != len) {
1329
+		free(buff);
1330
+		return NULL;
1331
+	}
1332
+	if (key != 0) {
1333
+		for (i=0 ; i < len; i++) {
1334
+			buff[i] = buff[i] ^ key;
1335
+		}
1336
+	}
1337
+	return buff;
1338
+}
... ...
@@ -29,10 +29,16 @@ typedef struct vba_project_tag {
29 29
 	int count;
30 30
 	char **name;
31 31
 	uint32_t *offset;
32
+	uint32_t *length;	/* for Word 6 macros */
33
+	unsigned char *key;	/* for Word 6 macros */
32 34
 	char *dir;
33 35
 } vba_project_t;
34 36
 
35 37
 vba_project_t *vba56_dir_read(const char *dir);
36 38
 unsigned char *vba_decompress(int fd, uint32_t offset, int *size);
37 39
 
40
+vba_project_t *wm_dir_read(const char *dir);
41
+unsigned char *wm_decrypt_macro(int fd, uint32_t offset, uint32_t len,
42
+					unsigned char key);
43
+
38 44
 #endif