git-svn: trunk@1723
Tomasz Kojm authored on 2005/09/19 08:19:28... | ... |
@@ -1,3 +1,9 @@ |
1 |
+Mon Sep 19 01:15:02 CEST 2005 (tk) |
|
2 |
+---------------------------------- |
|
3 |
+ * libclamav/elf.c: add cli_elfheader() |
|
4 |
+ * libclamav/execs.h: new file |
|
5 |
+ * libclamav/matcher.c: support ELF files in cli_caloff() |
|
6 |
+ |
|
1 | 7 |
Fri Sep 16 16:49:14 CEST 2005 (tk) |
2 | 8 |
---------------------------------- |
3 | 9 |
* libclamav/upx.c: fix possible buffer overflow (acab) |
... | ... |
@@ -32,6 +32,7 @@ |
32 | 32 |
#include "cltypes.h" |
33 | 33 |
#include "elf.h" |
34 | 34 |
#include "clamav.h" |
35 |
+#include "execs.h" |
|
35 | 36 |
|
36 | 37 |
#define DETECT_BROKEN (options & CL_SCAN_BLOCKBROKEN) |
37 | 38 |
|
... | ... |
@@ -61,7 +62,7 @@ int cli_scanelf(int desc, const char **virname, long int *scanned, const struct |
61 | 61 |
uint32_t entry, shoff, image; |
62 | 62 |
int i; |
63 | 63 |
|
64 |
- cli_dbgmsg("in cli_elfheader\n"); |
|
64 |
+ cli_dbgmsg("in cli_scanelf\n"); |
|
65 | 65 |
|
66 | 66 |
if(read(desc, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) { |
67 | 67 |
/* Not an ELF file? */ |
... | ... |
@@ -75,7 +76,7 @@ int cli_scanelf(int desc, const char **virname, long int *scanned, const struct |
75 | 75 |
} |
76 | 76 |
|
77 | 77 |
if(file_hdr.e_ident[4] != 1) { |
78 |
- cli_dbgmsg("ELF: 64-bit binaries not supported\n"); |
|
78 |
+ cli_dbgmsg("ELF: 64-bit binaries are not supported (yet)\n"); |
|
79 | 79 |
return CL_CLEAN; |
80 | 80 |
} |
81 | 81 |
|
... | ... |
@@ -180,7 +181,7 @@ int cli_scanelf(int desc, const char **virname, long int *scanned, const struct |
180 | 180 |
|
181 | 181 |
shentsize = EC16(file_hdr.e_shentsize); |
182 | 182 |
if(shentsize != sizeof(struct elf_section_hdr32)) { |
183 |
- cli_errmsg("ELF: shentsize != sizeof(struct elf_section_hdr32)\n"); |
|
183 |
+ cli_dbgmsg("ELF: shentsize != sizeof(struct elf_section_hdr32)\n"); |
|
184 | 184 |
if(DETECT_BROKEN) { |
185 | 185 |
if(virname) |
186 | 186 |
*virname = "Broken.Executable"; |
... | ... |
@@ -225,6 +226,7 @@ int cli_scanelf(int desc, const char **virname, long int *scanned, const struct |
225 | 225 |
|
226 | 226 |
cli_dbgmsg("ELF: Section %d\n", i); |
227 | 227 |
cli_dbgmsg("ELF: Section offset: %d\n", EC32(section_hdr[i].sh_offset)); |
228 |
+ cli_dbgmsg("ELF: Section size: %d\n", EC32(section_hdr[i].sh_size)); |
|
228 | 229 |
|
229 | 230 |
switch(EC32(section_hdr[i].sh_type)) { |
230 | 231 |
case 0x6: /* SHT_DYNAMIC */ |
... | ... |
@@ -297,3 +299,91 @@ int cli_scanelf(int desc, const char **virname, long int *scanned, const struct |
297 | 297 |
free(section_hdr); |
298 | 298 |
return CL_CLEAN; |
299 | 299 |
} |
300 |
+ |
|
301 |
+int cli_elfheader(int desc, struct cli_exe_info *elfinfo) |
|
302 |
+{ |
|
303 |
+ struct elf_file_hdr32 file_hdr; |
|
304 |
+ struct elf_section_hdr32 *section_hdr; |
|
305 |
+ uint16_t shnum, shentsize; |
|
306 |
+ uint32_t entry, shoff, image; |
|
307 |
+ int i; |
|
308 |
+ |
|
309 |
+ cli_dbgmsg("in cli_elfheader\n"); |
|
310 |
+ |
|
311 |
+ if(read(desc, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) { |
|
312 |
+ /* Not an ELF file? */ |
|
313 |
+ cli_dbgmsg("ELF: Can't read file header\n"); |
|
314 |
+ return -1; |
|
315 |
+ } |
|
316 |
+ |
|
317 |
+ if(memcmp(file_hdr.e_ident, "\x7f\x45\x4c\x46", 4)) { |
|
318 |
+ cli_dbgmsg("ELF: Not an ELF file\n"); |
|
319 |
+ return -1; |
|
320 |
+ } |
|
321 |
+ |
|
322 |
+ if(file_hdr.e_ident[4] != 1) { |
|
323 |
+ cli_dbgmsg("ELF: 64-bit binaries are not supported (yet)\n"); |
|
324 |
+ return -1; |
|
325 |
+ } |
|
326 |
+ |
|
327 |
+ if(file_hdr.e_ident[5] == 1) { |
|
328 |
+ image = 0x8048000; |
|
329 |
+#if WORDS_BIGENDIAN == 1 |
|
330 |
+ need_conversion = 1; |
|
331 |
+#endif |
|
332 |
+ } else { |
|
333 |
+ image = 0x10000; |
|
334 |
+#if WORDS_BIGENDIAN == 0 |
|
335 |
+ need_conversion = 1; |
|
336 |
+#endif |
|
337 |
+ } |
|
338 |
+ |
|
339 |
+ entry = EC32(file_hdr.e_entry); |
|
340 |
+ |
|
341 |
+ shnum = EC16(file_hdr.e_shnum); |
|
342 |
+ if(shnum > 256) { |
|
343 |
+ cli_dbgmsg("ELF: Suspicious number of sections\n"); |
|
344 |
+ return -1; |
|
345 |
+ } |
|
346 |
+ elfinfo->nsections = shnum; |
|
347 |
+ |
|
348 |
+ shentsize = EC16(file_hdr.e_shentsize); |
|
349 |
+ if(shentsize != sizeof(struct elf_section_hdr32)) { |
|
350 |
+ cli_dbgmsg("ELF: shentsize != sizeof(struct elf_section_hdr32)\n"); |
|
351 |
+ return -1; |
|
352 |
+ } |
|
353 |
+ |
|
354 |
+ shoff = EC32(file_hdr.e_shoff); |
|
355 |
+ if(lseek(desc, shoff, SEEK_SET) != shoff) { |
|
356 |
+ /* Possibly broken end of file */ |
|
357 |
+ return -1; |
|
358 |
+ } |
|
359 |
+ |
|
360 |
+ elfinfo->section = (struct cli_exe_section *) cli_calloc(elfinfo->nsections, sizeof(struct cli_exe_section)); |
|
361 |
+ if(!elfinfo->section) { |
|
362 |
+ cli_dbgmsg("ELF: Can't allocate memory for section headers\n"); |
|
363 |
+ return -1; |
|
364 |
+ } |
|
365 |
+ |
|
366 |
+ section_hdr = (struct elf_section_hdr32 *) cli_calloc(shnum, shentsize); |
|
367 |
+ if(!section_hdr) { |
|
368 |
+ cli_errmsg("ELF: Can't allocate memory for section headers\n"); |
|
369 |
+ return -1; |
|
370 |
+ } |
|
371 |
+ |
|
372 |
+ for(i = 0; i < shnum; i++) { |
|
373 |
+ |
|
374 |
+ if(read(desc, §ion_hdr[i], sizeof(struct elf_section_hdr32)) != sizeof(struct elf_section_hdr32)) { |
|
375 |
+ free(section_hdr); |
|
376 |
+ free(elfinfo->section); |
|
377 |
+ return -1; |
|
378 |
+ } |
|
379 |
+ |
|
380 |
+ elfinfo->section[i].rva = EC32(section_hdr[i].sh_addr); |
|
381 |
+ elfinfo->section[i].raw = EC32(section_hdr[i].sh_offset); |
|
382 |
+ elfinfo->section[i].rsz = EC32(section_hdr[i].sh_size); |
|
383 |
+ } |
|
384 |
+ |
|
385 |
+ free(section_hdr); |
|
386 |
+ return 0; |
|
387 |
+} |
... | ... |
@@ -24,6 +24,7 @@ |
24 | 24 |
|
25 | 25 |
#include "cltypes.h" |
26 | 26 |
#include "clamav.h" |
27 |
+#include "execs.h" |
|
27 | 28 |
|
28 | 29 |
struct elf_file_hdr32 { |
29 | 30 |
unsigned char e_ident[16]; |
... | ... |
@@ -57,4 +58,6 @@ struct elf_section_hdr32 { |
57 | 57 |
|
58 | 58 |
int cli_scanelf(int desc, 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); |
59 | 59 |
|
60 |
+int cli_elfheader(int desc, struct cli_exe_info *elfinfo); |
|
61 |
+ |
|
60 | 62 |
#endif |
61 | 63 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,37 @@ |
0 |
+/* |
|
1 |
+ * Copyright (C) 2005 Tomasz Kojm <tkojm@clamav.net> |
|
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 __EXECS_H |
|
19 |
+#define __EXECS_H |
|
20 |
+ |
|
21 |
+#include "cltypes.h" |
|
22 |
+ |
|
23 |
+struct cli_exe_section { |
|
24 |
+ uint32_t rva; |
|
25 |
+ uint32_t vsz; |
|
26 |
+ uint32_t raw; |
|
27 |
+ uint32_t rsz; |
|
28 |
+}; |
|
29 |
+ |
|
30 |
+struct cli_exe_info { |
|
31 |
+ uint32_t ep; |
|
32 |
+ uint16_t nsections; |
|
33 |
+ struct cli_exe_section *section; |
|
34 |
+}; |
|
35 |
+ |
|
36 |
+#endif |
... | ... |
@@ -34,12 +34,14 @@ |
34 | 34 |
#include "filetypes.h" |
35 | 35 |
#include "matcher.h" |
36 | 36 |
#include "pe.h" |
37 |
+#include "elf.h" |
|
38 |
+#include "execs.h" |
|
37 | 39 |
#include "special.h" |
38 | 40 |
|
39 | 41 |
#define MD5_BLOCKSIZE 4096 |
40 | 42 |
|
41 |
-#define TARGET_TABLE_SIZE 6 |
|
42 |
-static int targettab[TARGET_TABLE_SIZE] = { 0, CL_TYPE_MSEXE, CL_TYPE_MSOLE2, CL_TYPE_HTML, CL_TYPE_MAIL, CL_TYPE_GRAPHICS }; |
|
43 |
+#define TARGET_TABLE_SIZE 7 |
|
44 |
+static int targettab[TARGET_TABLE_SIZE] = { 0, CL_TYPE_MSEXE, CL_TYPE_MSOLE2, CL_TYPE_HTML, CL_TYPE_MAIL, CL_TYPE_GRAPHICS, CL_TYPE_ELF }; |
|
43 | 45 |
|
44 | 46 |
extern short cli_debug_flag; |
45 | 47 |
|
... | ... |
@@ -96,40 +98,47 @@ static struct cli_md5_node *cli_vermd5(const unsigned char *md5, const struct cl |
96 | 96 |
return NULL; |
97 | 97 |
} |
98 | 98 |
|
99 |
-static long int cli_caloff(const char *offstr, int fd) |
|
99 |
+static long int cli_caloff(const char *offstr, int fd, unsigned short ftype) |
|
100 | 100 |
{ |
101 |
- struct cli_pe_info peinfo; |
|
101 |
+ struct cli_exe_info exeinfo; |
|
102 |
+ int (*einfo)(int, struct cli_exe_info *) = NULL; |
|
102 | 103 |
long int offset = -1; |
103 | 104 |
int n; |
104 | 105 |
|
105 | 106 |
|
107 |
+ if(ftype == CL_TYPE_MSEXE) |
|
108 |
+ einfo = cli_peheader; |
|
109 |
+ else if(ftype == CL_TYPE_ELF) |
|
110 |
+ einfo = cli_elfheader; |
|
111 |
+ |
|
106 | 112 |
if(isdigit(offstr[0])) { |
107 | 113 |
return atoi(offstr); |
108 |
- } if(!strncmp(offstr, "EP+", 3) || !strncmp(offstr, "EP-", 3)) { |
|
114 |
+ |
|
115 |
+ } else if(einfo && (!strncmp(offstr, "EP+", 3) || !strncmp(offstr, "EP-", 3))) { |
|
109 | 116 |
if((n = lseek(fd, 0, SEEK_CUR)) == -1) { |
110 | 117 |
cli_dbgmsg("Invalid descriptor\n"); |
111 | 118 |
return -1; |
112 | 119 |
} |
113 | 120 |
lseek(fd, 0, SEEK_SET); |
114 |
- if(cli_peheader(fd, &peinfo)) { |
|
121 |
+ if(einfo(fd, &exeinfo)) { |
|
115 | 122 |
lseek(fd, n, SEEK_SET); |
116 | 123 |
return -1; |
117 | 124 |
} |
118 |
- free(peinfo.section); |
|
125 |
+ free(exeinfo.section); |
|
119 | 126 |
lseek(fd, n, SEEK_SET); |
120 | 127 |
|
121 | 128 |
if(offstr[2] == '+') |
122 |
- return peinfo.ep + atoi(offstr + 3); |
|
129 |
+ return exeinfo.ep + atoi(offstr + 3); |
|
123 | 130 |
else |
124 |
- return peinfo.ep - atoi(offstr + 3); |
|
131 |
+ return exeinfo.ep - atoi(offstr + 3); |
|
125 | 132 |
|
126 |
- } else if(offstr[0] == 'S') { |
|
133 |
+ } else if(einfo && offstr[0] == 'S') { |
|
127 | 134 |
if((n = lseek(fd, 0, SEEK_CUR)) == -1) { |
128 | 135 |
cli_dbgmsg("Invalid descriptor\n"); |
129 | 136 |
return -1; |
130 | 137 |
} |
131 | 138 |
lseek(fd, 0, SEEK_SET); |
132 |
- if(cli_peheader(fd, &peinfo)) { |
|
139 |
+ if(einfo(fd, &exeinfo)) { |
|
133 | 140 |
lseek(fd, n, SEEK_SET); |
134 | 141 |
return -1; |
135 | 142 |
} |
... | ... |
@@ -138,28 +147,28 @@ static long int cli_caloff(const char *offstr, int fd) |
138 | 138 |
if(!strncmp(offstr, "SL", 2)) { |
139 | 139 |
|
140 | 140 |
if(sscanf(offstr, "SL+%ld", &offset) != 1) { |
141 |
- free(peinfo.section); |
|
141 |
+ free(exeinfo.section); |
|
142 | 142 |
return -1; |
143 | 143 |
} |
144 | 144 |
|
145 |
- offset += peinfo.section[peinfo.nsections - 1].raw; |
|
145 |
+ offset += exeinfo.section[exeinfo.nsections - 1].raw; |
|
146 | 146 |
|
147 | 147 |
} else { |
148 | 148 |
|
149 | 149 |
if(sscanf(offstr, "S%d+%ld", &n, &offset) != 2) { |
150 |
- free(peinfo.section); |
|
150 |
+ free(exeinfo.section); |
|
151 | 151 |
return -1; |
152 | 152 |
} |
153 | 153 |
|
154 |
- if(n >= peinfo.nsections) { |
|
155 |
- free(peinfo.section); |
|
154 |
+ if(n >= exeinfo.nsections) { |
|
155 |
+ free(exeinfo.section); |
|
156 | 156 |
return -1; |
157 | 157 |
} |
158 | 158 |
|
159 |
- offset += peinfo.section[n].raw; |
|
159 |
+ offset += exeinfo.section[n].raw; |
|
160 | 160 |
} |
161 | 161 |
|
162 |
- free(peinfo.section); |
|
162 |
+ free(exeinfo.section); |
|
163 | 163 |
return offset; |
164 | 164 |
|
165 | 165 |
} else if(!strncmp(offstr, "EOF-", 4)) { |
... | ... |
@@ -226,7 +235,7 @@ int cli_validatesig(unsigned short target, unsigned short ftype, const char *off |
226 | 226 |
} |
227 | 227 |
|
228 | 228 |
if(offstr && desc != -1) { |
229 |
- long int off = cli_caloff(offstr, desc); |
|
229 |
+ long int off = cli_caloff(offstr, desc, ftype); |
|
230 | 230 |
|
231 | 231 |
if(off == -1) { |
232 | 232 |
cli_dbgmsg("Bad offset in signature (%s)\n", virname); |
... | ... |
@@ -42,6 +42,7 @@ |
42 | 42 |
#include "scanners.h" |
43 | 43 |
#include "rebuildpe.h" |
44 | 44 |
#include "str.h" |
45 |
+#include "execs.h" |
|
45 | 46 |
|
46 | 47 |
#define IMAGE_DOS_SIGNATURE 0x5a4d /* MZ */ |
47 | 48 |
#define IMAGE_DOS_SIGNATURE_OLD 0x4d5a /* ZM */ |
... | ... |
@@ -1479,7 +1480,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c |
1479 | 1479 |
return CL_CLEAN; |
1480 | 1480 |
} |
1481 | 1481 |
|
1482 |
-int cli_peheader(int desc, struct cli_pe_info *peinfo) |
|
1482 |
+int cli_peheader(int desc, struct cli_exe_info *peinfo) |
|
1483 | 1483 |
{ |
1484 | 1484 |
uint16_t e_magic; /* DOS signature ("MZ") */ |
1485 | 1485 |
uint32_t e_lfanew; /* address of new exe header */ |
... | ... |
@@ -1547,7 +1548,7 @@ int cli_peheader(int desc, struct cli_pe_info *peinfo) |
1547 | 1547 |
return -1; |
1548 | 1548 |
} |
1549 | 1549 |
|
1550 |
- peinfo->section = (struct SECTION *) cli_calloc(peinfo->nsections, sizeof(struct SECTION)); |
|
1550 |
+ peinfo->section = (struct cli_exe_section *) cli_calloc(peinfo->nsections, sizeof(struct cli_exe_section)); |
|
1551 | 1551 |
|
1552 | 1552 |
if(!peinfo->section) { |
1553 | 1553 |
cli_dbgmsg("Can't allocate memory for section headers\n"); |
... | ... |
@@ -23,7 +23,7 @@ |
23 | 23 |
#define __PE_H |
24 | 24 |
|
25 | 25 |
#include "clamav.h" |
26 |
-#include "rebuildpe.h" |
|
26 |
+#include "execs.h" |
|
27 | 27 |
|
28 | 28 |
struct pe_image_file_hdr { |
29 | 29 |
uint32_t Magic; |
... | ... |
@@ -94,14 +94,8 @@ struct pe_image_section_hdr { |
94 | 94 |
uint32_t Characteristics; |
95 | 95 |
}; |
96 | 96 |
|
97 |
-struct cli_pe_info { |
|
98 |
- uint32_t ep; /* raw entry point */ |
|
99 |
- uint16_t nsections; |
|
100 |
- struct SECTION *section; |
|
101 |
-}; |
|
102 |
- |
|
103 | 97 |
int cli_scanpe(int desc, 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); |
104 | 98 |
|
105 |
-int cli_peheader(int desc, struct cli_pe_info *peinfo); |
|
99 |
+int cli_peheader(int desc, struct cli_exe_info *peinfo); |
|
106 | 100 |
|
107 | 101 |
#endif |