Browse code

Tue Dec 14 11:15:22 GMT 2004 (trog) ----------------------------------- * sigtool/options.c sigtool/sigtool.c: New options: --vba and --vba-hex * sigtool/vba.c sigtool/vba.h: New files. Code to extract VBA/Word6 macros

git-svn: trunk@1183

Trog authored on 2004/12/14 20:20:01
Showing 6 changed files
... ...
@@ -1,3 +1,8 @@
1
+Tue Dec 14 11:15:22 GMT 2004 (trog)
2
+-----------------------------------
3
+  * sigtool/options.c sigtool/sigtool.c: New options: --vba and --vba-hex
4
+  * sigtool/vba.c sigtool/vba.h: New files. Code to extract VBA/Word6 macros
5
+
1 6
 Tue Dec 14 10:30:15 GMT 2004 (njh)
2 7
 ----------------------------------
3 8
   * libclamav/message.c:	better recovery if memory softlimit is hit
... ...
@@ -30,6 +30,8 @@ sigtool_SOURCES = \
30 30
     $(top_srcdir)/shared/misc.h \
31 31
     options.c \
32 32
     options.h \
33
+    vba.c \
34
+    vba.h \
33 35
     sigtool.c
34 36
 
35 37
 sigtool_LDADD = $(top_builddir)/clamscan/others.o 
... ...
@@ -58,6 +58,8 @@ int main(int argc, char **argv)
58 58
 	    {"unpack-current", 1, 0, 0},
59 59
 	    {"info", 1, 0, 'i'},
60 60
 	    {"list-sigs", 2, 0, 'l'},
61
+	    {"vba", 1, 0 ,0},
62
+	    {"vba-hex", 1, 0, 0},
61 63
 	    {0, 0, 0, 0}
62 64
     	};
63 65
 
... ...
@@ -52,6 +52,7 @@
52 52
 #include "../clamscan/others.h"
53 53
 #include "../libclamav/others.h"
54 54
 #include "../libclamav/str.h"
55
+#include "vba.h"
55 56
 
56 57
 #ifndef	O_BINARY
57 58
 #define	O_BINARY	0
... ...
@@ -169,6 +170,51 @@ void sigtool(struct optstruct *opt)
169 169
 
170 170
 	listsigs(opt);
171 171
 
172
+    } else if(optl(opt, "vba") || optl(opt, "vba-hex")) {
173
+            int fd, hex_output=0;
174
+	    char *dir;
175
+	    const char *tmpdir;
176
+
177
+
178
+	if (optl(opt, "vba-hex"))
179
+		hex_output = 1;
180
+ 
181
+	tmpdir = getenv("TMPDIR");
182
+                                                                                                                                                     
183
+	if(tmpdir == NULL)
184
+#ifdef P_tmpdir
185
+	    tmpdir = P_tmpdir;
186
+#else
187
+	    tmpdir = "/tmp";
188
+#endif
189
+                                                                                                                                                     
190
+        /* generate the temporary directory */
191
+        dir = cli_gentemp(tmpdir);
192
+        if(mkdir(dir, 0700)) {
193
+            mprintf("vba dump: Can't create temporary directory %s\n", dir);
194
+            return;
195
+        }
196
+                                                                                                                                     
197
+        if((fd = open(getargl(opt, "vba"), O_RDONLY)) == -1) {
198
+	    if((fd = open(getargl(opt, "vba-hex"), O_RDONLY)) == -1) {
199
+        	mprintf("Can't open file %s\n", getargl(opt, "vba"));
200
+        	exit(1);
201
+	    }
202
+        }
203
+
204
+        if(cli_ole2_extract(fd, dir, NULL)) {
205
+            cli_rmdirs(dir);
206
+            free(dir);
207
+	    close(fd);
208
+            return;
209
+        }                                                                                                                                        
210
+
211
+	close(fd);
212
+        sigtool_vba_scandir(dir, hex_output);
213
+                                                                                                                                                     
214
+        cli_rmdirs(dir);
215
+        free(dir);
216
+
172 217
     } else {
173 218
 
174 219
 	help();
... ...
@@ -773,6 +819,8 @@ void help(void)
773 773
     mprintf("    --unpack=FILE          -u FILE         Unpack a CVD file\n");
774 774
     mprintf("    --unpack-current=NAME                  Unpack local CVD\n");
775 775
     mprintf("    --list-sigs[=FILE]     -l[FILE]        List signature names\n");
776
+    mprintf("    --vba=FILE                             Extract VBA/Word6 macro code\n");
777
+    mprintf("    --vba-hex=FILE                         Extract Word6 macro code with hex values\n");
776 778
     mprintf("\n");
777 779
 
778 780
     exit(0);
779 781
new file mode 100644
... ...
@@ -0,0 +1,1064 @@
0
+/*
1
+ *  Copyright (C) 2004 Trog <trog@uncon.org>
2
+ *
3
+ *  This program is free software; you can redistribute it and/or modify
4
+ *  it under the terms of the GNU General Public License as published by
5
+ *  the Free Software Foundation; either version 2 of the License, or
6
+ *  (at your option) any later version.
7
+ *
8
+ *  This program is distributed in the hope that it will be useful,
9
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
+ *  GNU General Public License for more details.
12
+ *
13
+ *  You should have received a copy of the GNU General Public License
14
+ *  along with this program; if not, write to the Free Software
15
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16
+ */
17
+
18
+#include <stdio.h>
19
+#include <string.h>
20
+#include <stdlib.h>
21
+#include <unistd.h>
22
+#include <sys/types.h>
23
+#include <sys/stat.h>
24
+#include <fcntl.h>
25
+#include <dirent.h>
26
+#include <stdint.h>
27
+#include <clamav.h>
28
+#include <ctype.h>
29
+
30
+#include "../libclamav/vba_extract.h"
31
+#include "../libclamav/others.h"
32
+
33
+typedef struct mac_token_tag
34
+{
35
+    unsigned char token;
36
+    unsigned char *str;
37
+} mac_token_t;
38
+
39
+typedef struct mac_token2_tag
40
+{
41
+    uint16_t token;
42
+    unsigned char *str;
43
+
44
+} mac_token2_t;
45
+
46
+static char *get_unicode_name (char *name, int size)
47
+{
48
+    int i, j;
49
+    char *newname;
50
+
51
+    if (*name == 0 || size <= 0) {
52
+	return NULL;
53
+    }
54
+
55
+    newname = (char *) malloc (size * 2);
56
+    if (!newname) {
57
+	return NULL;
58
+    }
59
+    j = 0;
60
+    for (i = 0; i < size; i = i + 2) {
61
+	if (isprint (name[i])) {
62
+	    newname[j++] = name[i];
63
+	} else {
64
+	    if (name[i] < 10 && name[i] >= 0) {
65
+		newname[j++] = '_';
66
+		newname[j++] = name[i] + '0';
67
+	    }
68
+	    newname[j++] = '_';
69
+	}
70
+    }
71
+    newname[j] = '\0';
72
+    return newname;
73
+}
74
+
75
+void output_token (unsigned char token)
76
+{
77
+    int i;
78
+    mac_token_t mac_token[] = {
79
+	{0x01, "-"},
80
+	{0x02, "Not"},
81
+	{0x03, "And"},
82
+	{0x04, "Or"},
83
+	{0x05, "("},
84
+	{0x06, ")"},
85
+	{0x07, "+"},
86
+	{0x08, "-"},
87
+	{0x09, "/"},
88
+	{0x0a, "*"},
89
+	{0x0b, "Mod"},
90
+	{0x0c, "="},
91
+	{0x0d, "<>"},
92
+	{0x0e, "<"},
93
+	{0x0f, ">"},
94
+	{0x10, "<="},
95
+	{0x11, ">="},
96
+	{0x12, ","},
97
+	{0x18, "Resume"},
98
+	{0x19, ":"},
99
+	{0x1a, "End"},
100
+	{0x1b, "Sub"},
101
+	{0x1c, "Function"},
102
+	{0x1d, "If"},
103
+	{0x1e, "Then"},
104
+	{0x1f, "ElseIf"},
105
+	{0x20, "Else"},
106
+	{0x21, "While"},
107
+	{0x22, "Wend"},
108
+	{0x23, "For"},
109
+	{0x24, "To"},
110
+	{0x25, "Step"},
111
+	{0x26, "Next"},
112
+	{0x28, ";"},
113
+	{0x29, "Call"},
114
+	{0x2a, "Goto"},
115
+	{0x2c, "On"},
116
+	{0x2d, "Error"},
117
+	{0x2e, "Let"},
118
+	{0x2f, "Dim"},
119
+	{0x30, "Shared"},
120
+	{0x31, "Select"},
121
+	{0x32, "Is"},
122
+	{0x33, "Case"},
123
+	{0x34, "As"},
124
+	{0x35, "Redim"},
125
+	{0x36, "Print"},
126
+	{0x37, "Input"},
127
+	{0x38, "Line"},
128
+	{0x39, "Write"},
129
+	{0x3a, "Name"},
130
+	{0x3b, "Output"},
131
+	{0x3c, "Append"},
132
+	{0x3d, "Open"},
133
+	{0x3e, "GetCurValues"},
134
+	{0x3f, "Dialog"},
135
+	{0x40, "Super"},
136
+	{0x41, "Declare"},
137
+	{0x42, "Double"},
138
+	{0x43, "Integer"},
139
+	{0x44, "Long"},
140
+	{0x45, "Single"},
141
+	{0x46, "String"},
142
+	{0x47, "Cdecl"},
143
+	{0x48, "Alias"},
144
+	{0x49, "Any"},
145
+	{0x4a, "ToolsGetSpelling"},
146
+	{0x4b, "ToolsGetSynonyms"},
147
+	{0x4c, "Close"},
148
+	{0x4d, "Begin"},
149
+	{0x4e, "Lib"},
150
+	{0x4f, "Read"},
151
+	{0x50, "CheckDialog"},
152
+	{0x51, " "},		/* not sure about this one - some white space */
153
+	{0x52, "\t"},
154
+	{0x54, "EndIf"},
155
+	{0x64, "\n"},
156
+	{0x71, "#"},
157
+	{0x72, "\\"},
158
+	{0x00, NULL},
159
+    };
160
+
161
+    for (i = 0; mac_token[i].token != 0x00; i++) {
162
+	if (token == mac_token[i].token) {
163
+	    printf (" %s ", mac_token[i].str);
164
+	    return;
165
+	}
166
+    }
167
+    printf ("[#0x%x]", token);
168
+    return;
169
+}
170
+
171
+void output_token67 (uint16_t token)
172
+{
173
+    int i;
174
+    mac_token2_t mac_token[] = {
175
+	{0x0004, "HelpActivateWindow"},
176
+	{0x0009, "HelpAbout"},
177
+	{0x0016, "NextWindow"},
178
+	{0x001c, "DeleteWord"},
179
+	{0x0045, "GoBack"},
180
+	{0x0046, "SaveTemplate"},
181
+	{0x0048, "Cancel"},
182
+	{0x004e, "DocumentStatistics"},
183
+	{0x004f, "FileNew"},
184
+	{0x0050, "FileOpen"},
185
+	{0x0053, "FileSave"},
186
+	{0x0054, "FileSaveAs"},
187
+	{0x0056, "FileSummaryInfo"},
188
+	{0x0057, "FileTemplates"},
189
+	{0x0058, "FilePrint"},
190
+	{0x0061, "FilePrintSetup"},
191
+	{0x0063, "FileFind"},
192
+	{0x006c, "EditCut"},
193
+	{0x006d, "EditCopy"},
194
+	{0x006e, "EditPaste"},
195
+	{0x0070, "EditFind"},
196
+	{0x0074, "EditFindClearFormatting"},
197
+	{0x0075, "EditReplace"},
198
+	{0x0079, "EditReplaceClearFormatting"},
199
+	{0x007a, "EditGoTo"},
200
+	{0x007b, "EditAutoText"},
201
+	{0x0093, "ViewPage"},
202
+	{0x0098, "ToolsCustomize"},
203
+	{0x009f, "InsertBreak"},
204
+	{0x00a2, "InsertSymbol"},
205
+	{0x00a4, "InsertFile"},
206
+	{0x00a8, "EditBookmark"},
207
+	{0x00ac, "InsertObject"},
208
+	{0x00ae, "FormatFont"},
209
+	{0x00af, "FormatParagraph"},
210
+	{0x00b2, "FilePageSetup"},
211
+	{0x00bf, "ToolsSpelling"},
212
+	{0x00ca, "ToolsOptions"},
213
+	{0x00cc, "ToolsOptionsView"},
214
+	{0x00cb, "ToolsOptionsGeneral"},
215
+	{0x00d1, "ToolsOptionsSave"},
216
+	{0x00d5, "ToolsOptionsUserInfo"},
217
+	{0x00d7, "ToolsMacro"},
218
+	{0x00de, "Organizer"},
219
+	{0x00e1, "ToolsOptionsFileLocations"},
220
+	{0x00e9, "DocRestore"},
221
+	{0x00ed, "EditSelectAll"},
222
+	{0x00f3, "ClosePane"},
223
+	{0x0129, "UserDialog"},
224
+	{0x012c, "CopyFile"},
225
+	{0x012d, "FileNewDefault"},
226
+	{0x012e, "FilePrintDefault"},
227
+	{0x0143, "ViewToolbars"},
228
+	{0x0172, "InsertFootnote"},
229
+	{0x0179, "DrawRectangle"},
230
+	{0x017a, "ToolsAutoCorrect"},
231
+	{0x01b0, "ToolsCustomizeKeyboard"},
232
+	{0x01b1, "ToolsCustomizeMenus"},
233
+	{0x01d2, "DrawBringToFront"},
234
+	{0x01d3, "DrawSendToBack"},
235
+	{0x01e3, "InsertFormField"},
236
+	{0x01f7, "ToolsProtectDocument"},
237
+	{0x0202, "ShrinkFontOnePoint"},
238
+	{0x0209, "ToolsUnprotectDocument"},
239
+	{0x022f, "DrawFlipHorizontal"},
240
+	{0x0235, "FormatDrawingObject"},
241
+	{0x0241, "ViewZoom"},
242
+	{0x0246, "ToogleFull"},
243
+	{0x024a, "NewToolbar"},
244
+	{0x0265, "FileSendMail"},
245
+	{0x0267, "ToolsCustomizeMenuBar"},
246
+	{0x0270, "FileRoutingSlip"},
247
+	{0x0273, "ChooseButtonImage"},
248
+	{0x027b, "HelpTipOfTheDay"},
249
+	{0x0280, "Int"},
250
+	{0x0290, "MicrosoftMail"},
251
+	{0x0299, "ScreenRefresh"},
252
+	{0x02b0, "HelpContents"},
253
+	{0x0780, "Str$"},
254
+	{0x0e80, "Rnd"},
255
+	{0x2580, "FileName$"},
256
+	{0x2b80, "MsgBox"},
257
+	{0x2c80, "Beep"},
258
+	{0x5400, "FileSaveAs"},
259
+	{0x5600, "FileSummaryInfo"},
260
+	{0x8000, "Abs"},
261
+	{0x8001, "Sgn"},
262
+	{0x8002, "Int"},
263
+	{0x8003, "Len"},
264
+	{0x8004, "Asc"},
265
+	{0x8005, "Chr$"},
266
+	{0x8006, "Val"},
267
+	{0x8007, "Str$"},
268
+	{0x8008, "Left$"},
269
+	{0x8009, "Right$"},
270
+	{0x800a, "Mid$"},
271
+	{0x800b, "String$"},
272
+	{0x800c, "Date$"},
273
+	{0x800d, "Time$"},
274
+	{0x800e, "Rnd"},
275
+	{0x800f, "InStr"},
276
+	{0x8012, "Insert"},
277
+	{0x8013, "InsertPara"},
278
+	{0x8015, "Selection$"},
279
+	{0x801b, "ExistingBookMark"},
280
+	{0x8023, "IsDocumentDirty"},
281
+	{0x8024, "SetDocumentDirty"},
282
+	{0x8025, "FileName$"},
283
+	{0x8026, "CountFiles"},
284
+	{0x8027, "GetAutoText$"},
285
+	{0x802a, "SetAutoText"},
286
+	{0x802b, "MsgBox"},
287
+	{0x802c, "Beep"},
288
+	{0x802d, "Shell"},
289
+	{0x8032, "DocMove"},
290
+	{0x8033, "DocSize"},
291
+	{0x803a, "CountWindows"},
292
+	{0x803b, "WindowName$"},
293
+	{0x803e, "Window"},
294
+	{0x8041, "AppMinimize"},
295
+	{0x8042, "AppMaximize"},
296
+	{0x8043, "AppRestore"},
297
+	{0x8044, "DocMaximize"},
298
+	{0x8045, "GetProfileString$"},
299
+	{0x8046, "SetProfileString"},
300
+	{0x8047, "CharColor"},
301
+	{0x8048, "Bold"},
302
+	{0x8049, "Italic"},
303
+	{0x804e, "UnderLine"},
304
+	{0x8053, "CenterPara"},
305
+	{0x8054, "LeftPara"},
306
+	{0x8055, "RightPara"},
307
+	{0x8056, "JustifyPara"},
308
+	{0x805c, "DDEInitiate"},
309
+	{0x805d, "DDETerminate"},
310
+	{0x8053, "DDETerminateAll"},
311
+	{0x805f, "DDEExecute"},
312
+	{0x8060, "DDEPoke"},
313
+	{0x8061, "DDERequest$"},
314
+	{0x8062, "Activate"},
315
+	{0x8063, "AppActivate"},
316
+	{0x8064, "SendKeys"},
317
+	{0x806f, "ViewStatusBar"},
318
+	{0x8075, "ViewNormal"},
319
+	{0x8073, "ViewPage"},
320
+	{0x807a, "Font$"},
321
+	{0x807b, "CountOfFonts"},
322
+	{0x807c, "Font"},
323
+	{0x807d, "FontSize"},
324
+	{0x8081, "WW6_EditClear"},
325
+	{0x8082, "FileList"},
326
+	{0x8098, "ExtendSelection"},
327
+	{0x809e, "DisableInput"},
328
+	{0x809f, "DocClose"},
329
+	{0x80a0, "FileClose"},
330
+	{0x80a1, "File$"},
331
+	{0x80a2, "FileExit"},
332
+	{0x80a3, "FileSaveAll"},
333
+	{0x80a7, "Input$"},
334
+	{0x80a8, "Seek"},
335
+	{0x80a9, "Eof"},
336
+	{0x80aa, "Lof"},
337
+	{0x80ab, "Kill"},
338
+	{0x80ac, "ChDir"},
339
+	{0x80ad, "MkDir"},
340
+	{0x80ae, "RmDir"},
341
+	{0x80af, "UCase$"},
342
+	{0x80b0, "LCase$"},
343
+	{0x80b1, "InoutBox$"},
344
+	{0x80b3, "OnTime"},
345
+	{0x80b5, "AppInfo$"},
346
+	{0x80b6, "SelInfo"},
347
+	{0x80b7, "CountMacros"},
348
+	{0x80b8, "MacroName"},
349
+	{0x80b9, "CountFoundFiles"},
350
+	{0x80ba, "FoundFileName$"},
351
+	{0x80be, "MacroDesc$"},
352
+	{0x80c1, "KeyMacro$"},
353
+	{0x80c2, "MacroCopy"},
354
+	{0x80c3, "IsExecuteOnly"},
355
+	{0x80c7, "OKButton"},
356
+	{0x80c8, "CancelButton"},
357
+	{0x80c9, "Text"},
358
+	{0x80ca, "GroupBox"},
359
+	{0x80cb, "OptionButton"},
360
+	{0x80cc, "PushButton"},
361
+	{0x80d5, "ExitWindows"},
362
+	{0x80d6, "DisableAutoMacros"},
363
+	{0x80d7, "EditFindFound"},
364
+	{0x80d8, "CheckBox"},
365
+	{0x80d9, "TextBox"},
366
+	{0x80da, "ListBox"},
367
+	{0x80db, "OptionGroup"},
368
+	{0x80dc, "ComboBox"},
369
+	{0x80de, "WindowList"},
370
+	{0x80e8, "CountDirectories"},
371
+	{0x80e9, "GetDirectory$"},
372
+	{0x80ea, "LTrim$"},
373
+	{0x80eb, "RTrim$"},
374
+	{0x80ee, "Environ$"},
375
+	{0x80ef, "WaitCursor"},
376
+	{0x80f0, "DateSerial"},
377
+	{0x80f1, "DateValue"},
378
+	{0x80f2, "Day"},
379
+	{0x80f4, "Hour"},
380
+	{0x80f5, "Minute"},
381
+	{0x80f6, "Month"},
382
+	{0x80f7, "Now"},
383
+	{0x80f8, "WeekdayNow"},
384
+	{0x80f9, "Year"},
385
+	{0x80fa, "DocWindowHeight"},
386
+	{0x80fb, "DocWindowWidth"},
387
+	{0x80fd, "WinToDOS$"},
388
+	{0x80ff, "Second"},
389
+	{0x8100, "TimeValue"},
390
+	{0x8101, "Today"},
391
+	{0x8103, "SetAttr"},
392
+	{0x8105, "DocMinimize"},
393
+	{0x8107, "AppActivate"},
394
+	{0x810a, "AppHide"},
395
+	{0x810b, "AppIsRunning"},
396
+	{0x810c, "GetSystemInfo$"},
397
+	{0x810d, "GetPrivateProfileString$"},
398
+	{0x810e, "SetPrivateProfileString"},
399
+	{0x810f, "GetAttr"},
400
+	{0x8111, "ScreenUpdating"},
401
+	{0x8116, "SelectCurWord"},
402
+	{0x8118, "IsTemplateDirty"},
403
+	{0x8119, "SetTemplateDirty"},
404
+	{0x811b, "DlgEnable"},
405
+	{0x811f, "DlgText$"},
406
+	{0x8121, "AppShow"},
407
+	{0x8122, "DlgListBoxArray"},
408
+	{0x8125, "Picture"},
409
+	{0x8126, "DlgSetPicture"},
410
+	{0x8138, "DlgFocus"},
411
+	{0x813b, "BorderLineStyle"},
412
+	{0x813d, "MenuItemText$"},
413
+	{0x813e, "MenuItemMacro$"},
414
+	{0x813f, "CountMenus"},
415
+	{0x8140, "MenuText$"},
416
+	{0x8141, "CountMenuItems"},
417
+	{0x8145, "DocWindowPosTop"},
418
+	{0x8146, "DocWindowPosLeft"},
419
+	{0x8147, "Stop"},
420
+	{0x8148, "DropListBox"},
421
+	{0x8149, "RenameMenu"},
422
+	{0x814a, "FileCloseAll"},
423
+	{0x814b, "SortArray"},
424
+	{0x814c, "SetDocumentVar"},
425
+	{0x814d, "GetDocumentVar$"},
426
+	{0x8152, "IsMacro"},
427
+	{0x8153, "FileNameFromWindow$"},
428
+	{0x815b, "MoveToolbar"},
429
+	{0x816e, "MacID$"},
430
+	{0x8170, "GetSelEndPos"},
431
+	{0x8171, "SetSelRange"},
432
+	{0x8172, "GetText$"},
433
+	{0x8174, "DeleteButton"},
434
+	{0x8175, "AddButton"},
435
+	{0x8178, "AddAddIn"},
436
+	{0x8179, "GetAddInName$"},
437
+	{0x817c, "ResetButtonImage"},
438
+	{0x8180, "GetAddInId"},
439
+	{0x8181, "CountAddIns"},
440
+	{0x8183, "AddInState"},
441
+	{0x818c, "DefaultDir$"},
442
+	{0x818d, "FileNameInfo$"},
443
+	{0x818e, "MacroFileName$"},
444
+	{0x818f, "ViewHeader"},
445
+	{0x8190, "ViewFooter"},
446
+	{0x8195, "CountToolbars"},
447
+	{0x8196, "ToolbarName$"},
448
+	{0x8198, "ChDefaultDir"},
449
+	{0x8199, "EditUndo"},
450
+	{0x81a2, "FileQuit"},
451
+	{0x81a4, "FileConfirmConversions"},
452
+	{0x81d9, "CountToolbarButtons"},
453
+	{0x81da, "ToolbarButtonMacro$"},
454
+	{0x81dc, "AtEndOfDocument"},
455
+	{0xb780, "CountMacros"},
456
+	{0xb880, "MacroName$"},
457
+	{0xc000, "CharLeft"},
458
+	{0xc001, "CharRight"},
459
+	{0xc002, "WordLeft"},
460
+	{0xc003, "WordRight"},
461
+	{0xc004, "EndOfLine"},
462
+	{0xc007, "ParaDown"},
463
+	{0xc008, "LineUp"},
464
+	{0xc009, "LineDown"},
465
+	{0xc00a, "PageUp"},
466
+	{0xc00c, "StartOfLine"},
467
+	{0xc00d, "EndOfLine"},
468
+	{0xc010, "StartOfDocument"},
469
+	{0xc011, "EndOfDocument"},
470
+	{0xc012, "EditClear"},
471
+	{0xc024, "BorderTop"},
472
+	{0xc025, "BorderLeft"},
473
+	{0xc026, "BorderBottom"},
474
+	{0xc027, "BorderRight"},
475
+	{0xc280, "MacroCopy"},
476
+	{0x0000, NULL},
477
+    };
478
+    for (i = 0; mac_token[i].token != 0x0000; i++) {
479
+	if (token == mac_token[i].token) {
480
+	    printf ("%s", mac_token[i].str);
481
+	    return;
482
+	}
483
+    }
484
+    printf ("[#67(0x%x)]", token);
485
+    return;
486
+}
487
+
488
+void output_token73 (uint16_t token)
489
+{
490
+    int i;
491
+    mac_token2_t mac_token[] = {
492
+	{0x0001, ".Name"},
493
+	{0x0002, ".KeyCode"},
494
+	{0x0003, ".Context"},
495
+	{0x0004, ".ResetAll"},
496
+	{0x0007, ".Menu"},
497
+	{0x0008, ".MenuText"},
498
+	{0x0009, ".APPUSERNAME"},
499
+	{0x000b, ".Delete"},
500
+	{0x0012, ".SavedBy"},
501
+	{0x0014, ".DateCreatedFrom"},
502
+	{0x0015, ".DateCreatedTo"},
503
+	{0x0016, ".DateSavedFrom"},
504
+	{0x0017, ".DateSavedTo"},
505
+	{0x0020, ".ButtonFieldClicks"},
506
+	{0x0021, ".Font"},
507
+	{0x0022, ".Points"},
508
+	{0x0023, ".Color"},
509
+	{0x0024, ".Bold"},
510
+	{0x0025, ".Italic"},
511
+	{0x0027, ".Hidden"},
512
+	{0x0028, ".Underline"},
513
+	{0x002b, ".Position"},
514
+	{0x002d, ".Spacing"},
515
+	{0x002f, ".Printer"},
516
+	{0x0034, ".AutoSave"},
517
+	{0x0035, ".Units"},
518
+	{0x0036, ".Pagination"},
519
+	{0x0037, ".SummaryPrompt"},
520
+	{0x0039, ".Initials"},
521
+	{0x003a, ".Tabs"},
522
+	{0x003b, ".Spaces"},
523
+	{0x003c, ".Paras"},
524
+	{0x003d, ".Hyphens"},
525
+	{0x003e, ".ShowAll"},
526
+	{0x0041, ".TextBoundaries"},
527
+	{0x0046, ".PageWidth"},
528
+	{0x0047, ".PageHeight"},
529
+	{0x0049, ".TopMargin"},
530
+	{0x004a, ".BottomMargin"},
531
+	{0x004b, ".LeftMargin"},
532
+	{0x004c, ".RightMargin"},
533
+	{0x0052, ".Template"},
534
+	{0x0059, ".RecentFileCount"},
535
+	{0x005d, ".SmallCaps"},
536
+	{0x0060, ".Password"},
537
+	{0x0061, ".RecentFiles"},
538
+	{0x0062, ".Title"},
539
+	{0x0063, ".Subject"},
540
+	{0x0064, ".Author"},
541
+	{0x0065, ".Keywords"},
542
+	{0x0066, ".Comments"},
543
+	{0x0067, ".FileName"},
544
+	{0x0068, ".Directory"},
545
+	{0x006a, ".LastSavedDate"},
546
+	{0x006f, ".NumPages"},
547
+	{0x0074, ".Rename"},
548
+	{0x0075, ".NewName"},
549
+	{0x0078, ".SmartQuotes"},
550
+	{0x007f, ".Source"},
551
+	{0x0085, ".Insert"},
552
+	{0x0086, ".Destination"},
553
+	{0x0087, ".Type"},
554
+	{0x0091, ".Entry"},
555
+	{0x0092, ".Range"},
556
+	{0x0095, ".Link"},
557
+	{0x0098, ".Add"},
558
+	{0x009b, ".NewTemplate"},
559
+	{0x00a1, ".LeftIndent"},
560
+	{0x00a2, ".RightIndent"},
561
+	{0x00a3, ".FirstIndent"},
562
+	{0x00b9, ".NumCopies"},
563
+	{0x00ba, ".From"},
564
+	{0x00bb, ".To"},
565
+	{0x00cb, ".Format"},
566
+	{0x00cd, ".Replace"},
567
+	{0x00ce, ".WholeWord"},
568
+	{0x00cf, ".MatchCase"},
569
+	{0x00d7, ".CreateBackup"},
570
+	{0x00d8, ".LockAnnot"},
571
+	{0x00d9, ".Direction"},
572
+	{0x012b, ".UpdateLinks"},
573
+	{0x012e, ".Update"},
574
+	{0x0131, ".Text"},
575
+	{0x0136, ".Description"},
576
+	{0x0139, ".Setting"},
577
+	{0x013b, ".AllCaps"},
578
+	{0x0148, ".Category"},
579
+	{0x0149, ".ConfirmConversions"},
580
+	{0x014d, ".PicturePlaceHolders"},
581
+	{0x014e, ".FieldCodes"},
582
+	{0x0150, ".Show"},
583
+	{0x0156, ".FastSaves"},
584
+	{0x0157, ".SaveInterval"},
585
+	{0x0161, ".LineColor"},
586
+	{0x017d, ".Wrap"},
587
+	{0x0183, ".AutoFit"},
588
+	{0x0184, ".CharNum"},
589
+	{0x0194, ".Find"},
590
+	{0x0196, ".Path"},
591
+	{0x01a8, ".Background"},
592
+	{0x01a9, ".SearchPath"},
593
+	{0x01b1, ".Collate"},
594
+	{0x01b4, ".Button"},
595
+	{0x01b9, ".Remove"},
596
+	{0x01ba, ".Protect"},
597
+	{0x01d7, ".Store"},
598
+	{0x01da, ".Class"},
599
+	{0x01de, ".Hide"},
600
+	{0x01df, ".Toolbar"},
601
+	{0x01e0, ".ReplaceAll"},
602
+	{0x01eb, ".Address"},
603
+	{0x01f5, ".Run"},
604
+	{0x01f6, ".Edit"},
605
+	{0x0219, ".Revision"},
606
+	{0x021c, ".Pages"},
607
+	{0x021d, ".Words"},
608
+	{0x0232, ".WPHelp"},
609
+	{0x0233, ".WPDocNavKeys"},
610
+	{0x0234, ".SetDesc"},
611
+	{0x0255, ".AddToMru"},
612
+	{0x0272, ".With"},
613
+	{0x027e, ".ErrorBeeps"},
614
+	{0x0285, ".Goto"},
615
+	{0x0287, ".Copy"},
616
+	{0x028e, ".Caption"},
617
+	{0x0299, ".AddBelow"},
618
+	{0x02a4, ".Effects3d"},
619
+	{0x02ac, ".MenuType"},
620
+	{0x02ad, ".DraftFont"},
621
+	{0x02af, ".WrapToWindow"},
622
+	{0x02b0, ".Drawings"},
623
+	{0x02c6, ".SuperScript"},
624
+	{0x02c7, ".Subscript"},
625
+	{0x02c8, ".WritePassword"},
626
+	{0x02c9, ".RecommendReadOnly"},
627
+	{0x02ca, ".DocumentPassword"},
628
+	{0x02d6, ".InsertAs"},
629
+	{0x02dc, ".Formatting"},
630
+	{0x02de, ".InitialCaps"},
631
+	{0x02df, ".SentenceCaps"},
632
+	{0x02e0, ".Days"},
633
+	{0x02e1, ".ReplaceText"},
634
+	{0x02e4, ".Product"},
635
+	{0x02f1, ".SoundsLike"},
636
+	{0x02f2, ".KerningMin"},
637
+	{0x02f3, ".PatternMatch"},
638
+	{0x0308, ".EmbedFonts"},
639
+	{0x030a, ".Width"},
640
+	{0x030b, ".Height"},
641
+	{0x0316, ".SendMailAttach"},
642
+	{0x0318, ".Kerning"},
643
+	{0x0319, ".Exit"},
644
+	{0x031a, ".Enable"},
645
+	{0x031e, ".FormsData"},
646
+	{0x0320, ".BookMarks"},
647
+	{0x0327, ".LinkStyles"},
648
+	{0x032a, ".Message"},
649
+	{0x032d, ".AllAtOnce"},
650
+	{0x032f, ".TrackStatus"},
651
+	{0x0330, ".FillColor"},
652
+	{0x0332, ".FillPatternColor"},
653
+	{0x033a, ".RoundCorners"},
654
+	{0x0366, ".SearchName"},
655
+	{0x0370, ".BlueScreen"},
656
+	{0x0378, ".SubDir"},
657
+	{0x0388, ".HorizontalPos"},
658
+	{0x0389, ".HorizontalFrom"},
659
+	{0x038a, ".VerticalPos"},
660
+	{0x038b, ".VerticalFrom"},
661
+	{0x038f, ".Tab"},
662
+	{0x039a, ".Strikethrough"},
663
+	{0x039b, ".Face"},
664
+	{0x039d, ".NativePictureFormat"},
665
+	{0x03a2, ".LineType"},
666
+	{0x03a4, ".DisplayIcon"},
667
+	{0x03a8, ".IconFilename"},
668
+	{0x03a9, ".IconNumber"},
669
+	{0x03ac, ".GlobalDotPrompt"},
670
+	{0x03b2, ".NoReset"},
671
+	{0x03db, ".SaveAsAOCELetter"},
672
+	{0x041b, ".CapsLock"},
673
+	{0x0422, ".FindAllWordForms"},
674
+	{0x045e, ".VirusProtection"},
675
+	{0x6200, ".Title"},
676
+	{0x6300, ".Subject"},
677
+	{0x6400, ".Author"},
678
+	{0x6500, ".Keywords"},
679
+	{0x6600, ".Comments"},
680
+	{0xcb00, ".Format"},
681
+	{0x0000, NULL},
682
+    };
683
+
684
+    for (i = 0; mac_token[i].token != 0x0000; i++) {
685
+	if (token == mac_token[i].token) {
686
+	    printf ("%s", mac_token[i].str);
687
+	    return;
688
+	}
689
+    }
690
+    printf ("[#73(0x%x)]", token);
691
+    return;
692
+}
693
+
694
+void print_hex_buff (unsigned char *start, unsigned char *end, int hex_output)
695
+{
696
+    if (!hex_output) {
697
+	return;
698
+    }
699
+    printf ("[clam hex:");
700
+    while (start < end) {
701
+	printf (" %.2x", *start);
702
+	start++;
703
+    }
704
+    printf ("]\n");
705
+}
706
+
707
+void wm_decode_macro (unsigned char *buff, uint32_t len, int hex_output)
708
+{
709
+    int i, j;
710
+    uint8_t s_length;
711
+    uint16_t w_length, int_val;
712
+    unsigned char *tmp_buff, *tmp_name, *line_start;
713
+
714
+    i = 2;
715
+    line_start = buff;
716
+    while (i < len) {
717
+	switch (buff[i]) {
718
+	case 0x65:
719
+	    s_length = (uint8_t) buff[i + 1];
720
+	    tmp_buff = (unsigned char *) malloc (s_length + 1);
721
+	    strncpy (tmp_buff, buff + i + 2, s_length);
722
+	    tmp_buff[s_length] = '\0';
723
+	    print_hex_buff (line_start, buff + i + 2 + s_length, hex_output);
724
+	    printf ("\n%s", tmp_buff);
725
+	    free (tmp_buff);
726
+	    i += 2 + s_length;
727
+	    line_start = buff + i;
728
+	    break;
729
+	case 0x69:
730
+	    s_length = (uint8_t) buff[i + 1];
731
+	    tmp_buff = (unsigned char *) malloc (s_length + 1);
732
+	    strncpy (tmp_buff, buff + i + 2, s_length);
733
+	    tmp_buff[s_length] = '\0';
734
+	    printf (" %s", tmp_buff);
735
+	    free (tmp_buff);
736
+	    i += 2 + s_length;
737
+	    break;
738
+	case 0x6a:
739
+	    s_length = (uint8_t) buff[i + 1];
740
+	    tmp_buff = (unsigned char *) malloc (s_length + 1);
741
+	    strncpy (tmp_buff, buff + i + 2, s_length);
742
+	    tmp_buff[s_length] = '\0';
743
+	    printf (" \"%s\"", tmp_buff);
744
+	    free (tmp_buff);
745
+	    i += 2 + s_length;
746
+	    break;
747
+	case 0x6b:
748
+	    s_length = (uint8_t) buff[i + 1];
749
+	    tmp_buff = (unsigned char *) malloc (s_length + 1);
750
+	    strncpy (tmp_buff, buff + i + 2, s_length);
751
+	    tmp_buff[s_length] = '\0';
752
+	    printf (" '%s", tmp_buff);
753
+	    free (tmp_buff);
754
+	    i += 2 + s_length;
755
+	    break;
756
+	case 0x6d:
757
+	    s_length = (uint8_t) buff[i + 1];
758
+	    tmp_buff = (unsigned char *) malloc (s_length + 1);
759
+	    strncpy (tmp_buff, buff + i + 2, s_length);
760
+	    tmp_buff[s_length] = '\0';
761
+	    printf (" %s", tmp_buff);
762
+	    free (tmp_buff);
763
+	    i += 2 + s_length;
764
+	    break;
765
+	case 0x70:
766
+	    s_length = (uint8_t) buff[i + 1];
767
+	    tmp_buff = (unsigned char *) malloc (s_length + 1);
768
+	    strncpy (tmp_buff, buff + i + 2, s_length);
769
+	    tmp_buff[s_length] = '\0';
770
+	    printf ("REM%s", tmp_buff);
771
+	    free (tmp_buff);
772
+	    i += 2 + s_length;
773
+	    break;
774
+	case 0x76:
775
+	    s_length = (uint8_t) buff[i + 1];
776
+	    tmp_buff = (unsigned char *) malloc (s_length + 1);
777
+	    strncpy (tmp_buff, buff + i + 2, s_length);
778
+	    tmp_buff[s_length] = '\0';
779
+	    printf (" .%s", tmp_buff);
780
+	    free (tmp_buff);
781
+	    i += 2 + s_length;
782
+	    break;
783
+	case 0x77:
784
+	    s_length = (uint8_t) buff[i + 1];
785
+	    tmp_buff = (unsigned char *) malloc (s_length + 1);
786
+	    strncpy (tmp_buff, buff + i + 2, s_length);
787
+	    tmp_buff[s_length] = '\0';
788
+	    printf ("%s", tmp_buff);
789
+	    free (tmp_buff);
790
+	    i += 2 + s_length;
791
+	    break;
792
+	case 0x79:		/* unicode "string" */
793
+	    w_length = (uint16_t) (buff[i + 2] << 8) + buff[i + 1];
794
+	    tmp_buff = (unsigned char *) malloc ((w_length * 2) + 1);
795
+	    memcpy (tmp_buff, buff + i + 3, w_length * 2);
796
+	    tmp_name = get_unicode_name (tmp_buff, w_length * 2);
797
+	    free (tmp_buff);
798
+	    printf ("\"%s\"", tmp_name);
799
+	    free (tmp_name);
800
+	    i += 3 + (w_length * 2);
801
+	    break;
802
+
803
+	case 0x7c:		/* unicode 'string */
804
+	    s_length = (uint8_t) buff[i + 1];
805
+	    tmp_buff = (unsigned char *) malloc ((s_length * 2) + 1);
806
+	    memcpy (tmp_buff, buff + i + 2, s_length * 2);
807
+	    tmp_name = get_unicode_name (tmp_buff, s_length * 2);
808
+	    free (tmp_buff);
809
+	    printf ("'%s", tmp_name);
810
+	    free (tmp_name);
811
+	    i += 2 + (s_length * 2);
812
+	    break;
813
+
814
+	case 0x66:
815
+	    int_val = (uint8_t) (buff[i + 2] << 8) + buff[i + 1];
816
+	    print_hex_buff (line_start, buff + i + 3, hex_output);
817
+	    printf ("\n%d", int_val);
818
+	    i += 3;
819
+	    line_start = buff + i;
820
+	    break;
821
+	case 0x67:
822
+	    w_length = (uint16_t) (buff[i + 2] << 8) + buff[i + 1];
823
+	    output_token67 (w_length);
824
+	    i += 3;
825
+	    break;
826
+	case 0x68:
827
+	    /* 8-byte float */
828
+	    printf ("(float)");
829
+	    i += 9;
830
+	    break;
831
+	case 0x6c:
832
+	    int_val = (uint16_t) (buff[i + 2] << 8) + buff[i + 1];
833
+	    printf (" %d", int_val);
834
+	    i += 3;
835
+	    break;
836
+	case 0x6e:
837
+	    s_length = (uint8_t) buff[i + 1];
838
+	    for (j = 0; j < s_length; j++) {
839
+		printf (" ");
840
+	    }
841
+	    i += 2;
842
+	    break;
843
+	case 0x6f:
844
+	    s_length = (uint8_t) buff[i + 1];
845
+	    for (j = 0; j < s_length; j++) {
846
+		printf ("\t");
847
+	    }
848
+	    i += 2;
849
+	    break;
850
+	case 0x73:
851
+	    w_length = (uint16_t) (buff[i + 2] << 8) + buff[i + 1];
852
+	    output_token73 (w_length);
853
+	    i += 3;
854
+	    break;
855
+	case 0x64:
856
+	    print_hex_buff (line_start, buff + i + 1, hex_output);
857
+	    printf ("\n");
858
+	    i++;
859
+	    line_start = buff + i;
860
+	    break;
861
+	default:
862
+	    output_token (buff[i]);
863
+	    i++;
864
+	    break;
865
+	}
866
+    }
867
+    print_hex_buff (line_start, buff + i, hex_output);
868
+}
869
+
870
+static int sigtool_scandir (const char *dirname, int hex_output)
871
+{
872
+    DIR *dd;
873
+    struct dirent *dent;
874
+    struct stat statbuf;
875
+    char *fname;
876
+    const char *tmpdir;
877
+    char *dir;
878
+    int retval, ret = CL_CLEAN, desc;
879
+
880
+
881
+    if ((dd = opendir (dirname)) != NULL) {
882
+	while ((dent = readdir (dd))) {
883
+	    if (dent->d_ino) {
884
+		if (strcmp (dent->d_name, ".") && strcmp (dent->d_name, "..")) {
885
+		    /* build the full name */
886
+		    fname = (char *) cli_calloc (strlen (dirname) + strlen (dent->d_name) + 2, sizeof (char));
887
+		    sprintf (fname, "%s/%s", dirname, dent->d_name);
888
+
889
+		    /* stat the file */
890
+		    if (lstat (fname, &statbuf) != -1) {
891
+			if (S_ISDIR (statbuf.st_mode) && !S_ISLNK (statbuf.st_mode)) {
892
+			    if (sigtool_scandir (fname, hex_output)) {
893
+				free (fname);
894
+				closedir (dd);
895
+				return CL_VIRUS;
896
+			    }
897
+			} else {
898
+			    if (S_ISREG (statbuf.st_mode)) {
899
+				tmpdir = getenv ("TMPDIR");
900
+
901
+				if (tmpdir == NULL)
902
+#ifdef P_tmpdir
903
+				    tmpdir = P_tmpdir;
904
+#else
905
+				    tmpdir = "/tmp";
906
+#endif
907
+
908
+				/* generate the temporary directory */
909
+				dir = cli_gentemp (tmpdir);
910
+				if (mkdir (dir, 0700)) {
911
+				    printf ("Can't create temporary directory %s\n", dir);
912
+				    return CL_ETMPDIR;
913
+				}
914
+
915
+				if ((desc = open (fname, O_RDONLY)) == -1) {
916
+				    printf ("Can't open file %s\n", fname);
917
+				    return 1;
918
+				}
919
+
920
+				if ((ret = cli_ole2_extract (desc, dir, NULL))) {
921
+				    printf ("ERROR %s\n", cl_strerror (ret));
922
+				    cli_rmdirs (dir);
923
+				    free (dir);
924
+				    return ret;
925
+				}
926
+
927
+				sigtool_vba_scandir (dir, hex_output);
928
+
929
+				cli_rmdirs (dir);
930
+				free (dir);
931
+			    }
932
+			}
933
+
934
+		    }
935
+		    free (fname);
936
+		}
937
+	    }
938
+	}
939
+    } else {
940
+	cli_errmsg ("Can't open directory %s.\n", dirname);
941
+	return CL_EOPEN;
942
+    }
943
+
944
+    closedir (dd);
945
+    return 0;
946
+}
947
+
948
+int sigtool_vba_scandir (const char *dirname, int hex_output)
949
+{
950
+    int ret = CL_CLEAN, i, fd, data_len;
951
+    vba_project_t *vba_project;
952
+    DIR *dd;
953
+    struct dirent *dent;
954
+    struct stat statbuf;
955
+    char *fname, *fullname;
956
+    unsigned char *data;
957
+
958
+    cli_dbgmsg ("VBA scan dir: %s\n", dirname);
959
+    if ((vba_project = (vba_project_t *) vba56_dir_read (dirname))) {
960
+
961
+	for (i = 0; i < vba_project->count; i++) {
962
+	    fullname = (char *) malloc (strlen (vba_project->dir) + strlen (vba_project->name[i]) + 2);
963
+	    sprintf (fullname, "%s/%s", vba_project->dir, vba_project->name[i]);
964
+	    fd = open (fullname, O_RDONLY);
965
+	    if (fd == -1) {
966
+		cli_errmsg ("Scan->OLE2 -> Can't open file %s\n", fullname);
967
+		free (fullname);
968
+		ret = CL_EOPEN;
969
+		break;
970
+	    }
971
+	    free (fullname);
972
+	    cli_dbgmsg ("decompress VBA project '%s'\n", vba_project->name[i]);
973
+	    printf ("-------------- start of %s ------------------\n", vba_project->name[i]);
974
+	    data = (unsigned char *) vba_decompress (fd, vba_project->offset[i], &data_len);
975
+	    close (fd);
976
+
977
+	    if (!data) {
978
+		cli_dbgmsg ("WARNING: VBA project '%s' decompressed to NULL\n", vba_project->name[i]);
979
+	    } else {
980
+		data = (char *) realloc (data, data_len + 1);
981
+		data[data_len] = '\0';
982
+		printf ("%s", data);
983
+		free (data);
984
+
985
+	    }
986
+	    printf ("-------------- end of %s ------------------\n", vba_project->name[i]);
987
+	}
988
+
989
+	for (i = 0; i < vba_project->count; i++)
990
+	    free (vba_project->name[i]);
991
+	free (vba_project->name);
992
+	free (vba_project->dir);
993
+	free (vba_project->offset);
994
+	free (vba_project);
995
+    } else if ((fullname = ppt_vba_read (dirname))) {
996
+	if (sigtool_scandir (fullname, hex_output) == CL_VIRUS) {
997
+	    ret = CL_VIRUS;
998
+	}
999
+	cli_rmdirs (fullname);
1000
+	free (fullname);
1001
+    } else if ((vba_project = (vba_project_t *) wm_dir_read (dirname))) {
1002
+	for (i = 0; i < vba_project->count; i++) {
1003
+	    fullname = (char *) malloc (strlen (vba_project->dir) + strlen (vba_project->name[i]) + 2);
1004
+	    sprintf (fullname, "%s/%s", vba_project->dir, vba_project->name[i]);
1005
+	    fd = open (fullname, O_RDONLY);
1006
+	    if (fd == -1) {
1007
+		cli_errmsg ("Scan->OLE2 -> Can't open file %s\n", fullname);
1008
+		free (fullname);
1009
+		ret = CL_EOPEN;
1010
+		break;
1011
+	    }
1012
+	    free (fullname);
1013
+	    cli_dbgmsg ("decompress WM project '%s' macro %d\n", vba_project->name[i], i);
1014
+	    printf ("\n\n-------------- start of macro:%d key:%d length:%d ------------------\n", i,
1015
+		    vba_project->key[i], vba_project->length[i]);
1016
+	    data = (unsigned char *) wm_decrypt_macro (fd, vba_project->offset[i], vba_project->length[i],
1017
+						    vba_project->key[i]);
1018
+	    close (fd);
1019
+
1020
+	    if (!data) {
1021
+		cli_dbgmsg ("WARNING: WM project '%s' macro %d decrypted to NULL\n", vba_project->name[i], i);
1022
+	    } else {
1023
+		wm_decode_macro (data, vba_project->length[i], hex_output);
1024
+		free (data);
1025
+	    }
1026
+	    printf ("\n-------------- end of macro %d ------------------\n\n", i);
1027
+	}
1028
+	for (i = 0; i < vba_project->count; i++)
1029
+	    free (vba_project->name[i]);
1030
+	free (vba_project->key);
1031
+	free (vba_project->length);
1032
+	free (vba_project->offset);
1033
+	free (vba_project->name);
1034
+	free (vba_project->dir);
1035
+	free (vba_project);
1036
+    }
1037
+
1038
+    if ((dd = opendir (dirname)) != NULL) {
1039
+	while ((dent = readdir (dd))) {
1040
+	    if (dent->d_ino) {
1041
+		if (strcmp (dent->d_name, ".") && strcmp (dent->d_name, "..")) {
1042
+		    /* build the full name */
1043
+		    fname = calloc (strlen (dirname) + strlen (dent->d_name) + 2, sizeof (char));
1044
+		    sprintf (fname, "%s/%s", dirname, dent->d_name);
1045
+
1046
+		    /* stat the file */
1047
+		    if (lstat (fname, &statbuf) != -1) {
1048
+			if (S_ISDIR (statbuf.st_mode) && !S_ISLNK (statbuf.st_mode))
1049
+			    sigtool_vba_scandir (fname, hex_output);
1050
+		    }
1051
+		    free (fname);
1052
+		}
1053
+	    }
1054
+	}
1055
+    } else {
1056
+	cli_errmsg ("ScanDir -> Can't open directory %s.\n", dirname);
1057
+	return CL_EOPEN;
1058
+    }
1059
+
1060
+
1061
+    closedir (dd);
1062
+    return ret;
1063
+}
0 1064
new file mode 100644
... ...
@@ -0,0 +1,25 @@
0
+/*
1
+ *  Copyright (C) 2004 Trog <trog@uncon.org>
2
+ *
3
+ *  This program is free software; you can redistribute it and/or modify
4
+ *  it under the terms of the GNU General Public License as published by
5
+ *  the Free Software Foundation; either version 2 of the License, or
6
+ *  (at your option) any later version.
7
+ *
8
+ *  This program is distributed in the hope that it will be useful,
9
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
+ *  GNU General Public License for more details.
12
+ *
13
+ *  You should have received a copy of the GNU General Public License
14
+ *  along with this program; if not, write to the Free Software
15
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16
+ */
17
+ 
18
+#ifndef __VBA_H
19
+#define __VBA_H
20
+
21
+extern int hex_output;
22
+int sigtool_vba_scandir(const char *dirname, int hex_output);
23
+
24
+#endif