Browse code

first commit of ELF scanning module

git-svn: trunk@1708

Tomasz Kojm authored on 2005/08/25 12:03:39
Showing 3 changed files
... ...
@@ -1,3 +1,8 @@
1
+Thu Aug 25 04:54:51 CEST 2005 (tk)
2
+----------------------------------
3
+  * libclamav/elf.[ch]: new files (initial version of ELF scanning module),
4
+			not yet activated
5
+
1 6
 Sun Aug 21 03:19:15 CEST 2005 (tk)
2 7
 ----------------------------------
3 8
   * libclamav: improve scanning of zip files (patch by Daniel Fahlgren
4 9
new file mode 100644
... ...
@@ -0,0 +1,273 @@
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
+#if HAVE_CONFIG_H
19
+#include "clamav-config.h"
20
+#endif
21
+
22
+#include <stdio.h>
23
+#include <string.h>
24
+#include <sys/types.h>
25
+#include <sys/stat.h>
26
+#include <fcntl.h>
27
+#include <sys/stat.h>
28
+#include <unistd.h>
29
+#include <time.h>
30
+
31
+#include "cltypes.h"
32
+#include "elf.h"
33
+#include "clamav.h"
34
+
35
+#define DETECT_BROKEN		    (options & CL_SCAN_BLOCKBROKEN)
36
+
37
+#if WORDS_BIGENDIAN == 0
38
+#define EC16(v)	(v)
39
+#define EC32(v) (v)
40
+#else
41
+static inline uint16_t EC16(uint16_t v)
42
+{
43
+    return ((v >> 8) + (v << 8));
44
+}
45
+
46
+static inline uint32_t EC32(uint32_t v)
47
+{
48
+    return ((v >> 24) | ((v & 0x00FF0000) >> 8) | ((v & 0x0000FF00) << 8) | (v << 24));
49
+}
50
+#endif
51
+
52
+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)
53
+{
54
+	struct elf_file_hdr32 file_hdr;
55
+	struct elf_section_hdr32 *section_hdr;
56
+	uint16_t shnum, shentsize;
57
+	uint32_t entry, shoff;
58
+	int i;
59
+
60
+    cli_dbgmsg("in cli_elfheader\n");
61
+
62
+    if(read(desc, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
63
+	/* Not an ELF file? */
64
+	cli_dbgmsg("ELF: Can't read file header\n");
65
+	return CL_CLEAN;
66
+    }
67
+
68
+    if(memcmp(file_hdr.e_ident, "\x7f\x45\x4c\x46", 4)) {
69
+	cli_dbgmsg("ELF: Not an ELF file\n");
70
+	return CL_CLEAN;
71
+    }
72
+
73
+    switch(EC16(file_hdr.e_type)) {
74
+	case 0x0: /* ET_NONE */
75
+	    cli_dbgmsg("ELF: File type: None\n");
76
+	    break;
77
+	case 0x1: /* ET_REL */
78
+	    cli_dbgmsg("ELF: File type: Relocatable\n");
79
+	    break;
80
+	case 0x2: /* ET_EXEC */
81
+	    cli_dbgmsg("ELF: File type: Executable\n");
82
+	    break;
83
+	case 0x3: /* ET_DYN */
84
+	    cli_dbgmsg("ELF: File type: Core\n");
85
+	    break;
86
+	case 0x4: /* ET_CORE */
87
+	    cli_dbgmsg("ELF: File type: Core\n");
88
+	    break;
89
+	default:
90
+	    cli_dbgmsg("ELF: File type: Unknown (%d)\n", EC16(file_hdr.e_type));
91
+    }
92
+
93
+    switch(EC16(file_hdr.e_machine)) {
94
+	/* Due to a huge list, we only include the most popular machines here */
95
+	case 0x0: /* EM_NONE */
96
+	    cli_dbgmsg("ELF: Machine type: None\n");
97
+	    break;
98
+	case 0x2: /* EM_SPARC */
99
+	    cli_dbgmsg("ELF: Machine type: SPARC\n");
100
+	    break;
101
+	case 0x3: /* EM_386 */
102
+	    cli_dbgmsg("ELF: Machine type: Intel 80386\n");
103
+	    break;
104
+	case 0x4: /* EM_68K */
105
+	    cli_dbgmsg("ELF: Machine type: Motorola 68000\n");
106
+	    break;
107
+	case 0x8: /* EM_MIPS */
108
+	    cli_dbgmsg("ELF: Machine type: MIPS RS3000\n");
109
+	    break;
110
+	case 0x15: /* EM_PARISC */
111
+	    cli_dbgmsg("ELF: Machine type: HPPA\n");
112
+	    break;
113
+	case 0x20: /* EM_PPC */
114
+	    cli_dbgmsg("ELF: Machine type: PowerPC\n");
115
+	    break;
116
+	case 0x21: /* EM_PPC64 */
117
+	    cli_dbgmsg("ELF: Machine type: PowerPC 64-bit\n");
118
+	    break;
119
+	case 0x22: /* EM_S390 */
120
+	    cli_dbgmsg("ELF: Machine type: IBM S390\n");
121
+	    break;
122
+	case 0x40: /* EM_ARM */
123
+	    cli_dbgmsg("ELF: Machine type: ARM\n");
124
+	    break;
125
+	case 0x41: /* EM_FAKE_ALPHA */
126
+	    cli_dbgmsg("ELF: Machine type: Digital Alpha\n");
127
+	    break;
128
+	case 0x43: /* EM_SPARCV9 */
129
+	    cli_dbgmsg("ELF: Machine type: SPARC v9 64-bit\n");
130
+	    break;
131
+	case 0x50: /* EM_IA_64 */
132
+	    cli_dbgmsg("ELF: Machine type: IA64\n");
133
+	    break;
134
+	default:
135
+	    cli_dbgmsg("ELF: Machine type: Unknown (%d)\n", EC16(file_hdr.e_machine));
136
+    }
137
+
138
+    entry = EC32(file_hdr.e_entry);
139
+    cli_dbgmsg("ELF: Entry point address: 0x%.8x\n", entry);
140
+    cli_dbgmsg("ELF: Entry point offset: 0x%.8x (%d)\n", entry - 0x8048000, entry - 0x8048000);
141
+
142
+    shnum = EC16(file_hdr.e_shnum);
143
+    cli_dbgmsg("ELF: Number of sections: %d\n", shnum);
144
+    if(shnum > 256) {
145
+	cli_dbgmsg("ELF: Suspicious number of sections\n");
146
+        if(DETECT_BROKEN) {
147
+	    if(virname)
148
+            *virname = "Broken.Executable";
149
+            return CL_VIRUS;
150
+        }
151
+	return CL_EFORMAT;
152
+    }
153
+
154
+    shentsize = EC16(file_hdr.e_shentsize);
155
+    if(shentsize != sizeof(struct elf_section_hdr32)) {
156
+	cli_errmsg("ELF: shentsize != sizeof(struct elf_section_hdr32)\n");
157
+        if(DETECT_BROKEN) {
158
+	    if(virname)
159
+            *virname = "Broken.Executable";
160
+            return CL_VIRUS;
161
+        }
162
+	return CL_EFORMAT;
163
+    }
164
+
165
+    shoff = EC32(file_hdr.e_shoff);
166
+    cli_dbgmsg("ELF: Section header table offset: %d\n", shoff);
167
+    if(lseek(desc, shoff, SEEK_SET) != shoff) {
168
+	/* Possibly broken end of file */
169
+        if(DETECT_BROKEN) {
170
+	    if(virname)
171
+            *virname = "Broken.Executable";
172
+            return CL_VIRUS;
173
+        }
174
+	return CL_CLEAN;
175
+    }
176
+
177
+    section_hdr = (struct elf_section_hdr32 *) cli_calloc(shnum, shentsize);
178
+    if(!section_hdr) {
179
+	cli_dbgmsg("ELF: Can't allocate memory for section headers\n");
180
+	return CL_EMEM;
181
+    }
182
+
183
+    cli_dbgmsg("------------------------------------\n");
184
+
185
+    for(i = 0; i < shnum; i++) {
186
+
187
+	if(read(desc, &section_hdr[i], sizeof(struct elf_section_hdr32)) != sizeof(struct elf_section_hdr32)) {
188
+            cli_dbgmsg("ELF: Can't read section header\n");
189
+            cli_dbgmsg("ELF: Possibly broken ELF file\n");
190
+            free(section_hdr);
191
+            if(DETECT_BROKEN) {
192
+                if(virname)
193
+                    *virname = "Broken.Executable";
194
+                return CL_VIRUS;
195
+            }
196
+            return CL_CLEAN;
197
+        }
198
+
199
+	cli_dbgmsg("ELF: Section %d\n", i);
200
+	cli_dbgmsg("ELF: Section offset: %d\n", EC32(section_hdr[i].sh_offset));
201
+
202
+	switch(EC32(section_hdr[i].sh_type)) {
203
+	    case 0x6: /* SHT_DYNAMIC */
204
+		cli_dbgmsg("ELF: Section type: Dynamic linking information\n");
205
+		break;
206
+	    case 0xb: /* SHT_DYNSYM */
207
+		cli_dbgmsg("ELF: Section type: Symbols for dynamic linking\n");
208
+		break;
209
+	    case 0xf: /* SHT_FINI_ARRAY */
210
+		cli_dbgmsg("ELF: Section type: Array of pointers to termination functions\n");
211
+		break;
212
+	    case 0x5: /* SHT_HASH */
213
+		cli_dbgmsg("ELF: Section type: Symbol hash table\n");
214
+		break;
215
+	    case 0xe: /* SHT_INIT_ARRAY */
216
+		cli_dbgmsg("ELF: Section type: Array of pointers to initialization functions\n");
217
+		break;
218
+	    case 0x8: /* SHT_NOBITS */
219
+		cli_dbgmsg("ELF: Section type: Empty section (NOBITS)\n");
220
+		break;
221
+	    case 0x7: /* SHT_NOTE */
222
+		cli_dbgmsg("ELF: Section type: Note section\n");
223
+		break;
224
+	    case 0x0: /* SHT_NULL */
225
+		cli_dbgmsg("ELF: Section type: Null (no associated section)\n");
226
+		break;
227
+	    case 0x10: /* SHT_PREINIT_ARRAY */
228
+		cli_dbgmsg("ELF: Section type: Array of pointers to preinit functions\n");
229
+		break;
230
+	    case 0x1: /* SHT_PROGBITS */
231
+		cli_dbgmsg("ELF: Section type: Program information\n");
232
+		break;
233
+	    case 0x9: /* SHT_REL */
234
+		cli_dbgmsg("ELF: Section type: Relocation entries w/o explicit addends\n");
235
+		break;
236
+	    case 0x4: /* SHT_RELA */
237
+		cli_dbgmsg("ELF: Section type: Relocation entries with explicit addends\n");
238
+		break;
239
+	    case 0x3: /* SHT_STRTAB */
240
+		cli_dbgmsg("ELF: Section type: String table\n");
241
+		break;
242
+	    case 0x2: /* SHT_SYMTAB */
243
+		cli_dbgmsg("ELF: Section type: Symbol table\n");
244
+		break;
245
+	    case 0x6ffffffd: /* SHT_GNU_verdef */
246
+		cli_dbgmsg("ELF: Section type: Provided symbol versions\n");
247
+		break;
248
+	    case 0x6ffffffe: /* SHT_GNU_verneed */
249
+		cli_dbgmsg("ELF: Section type: Required symbol versions\n");
250
+		break;
251
+	    case 0x6fffffff: /* SHT_GNU_versym */
252
+		cli_dbgmsg("ELF: Section type: Symbol Version Table\n");
253
+		break;
254
+	    default :
255
+		cli_dbgmsg("ELF: Section type: Unknown\n");
256
+	}
257
+
258
+	if(EC32(section_hdr[i].sh_flags) & 0x1) /* SHF_WRITE */
259
+	    cli_dbgmsg("ELF: Section contains writable data\n");
260
+
261
+	if(EC32(section_hdr[i].sh_flags) & 0x2) /* SHF_ALLOC */
262
+	    cli_dbgmsg("ELF: Section occupies memory\n");
263
+
264
+	if(EC32(section_hdr[i].sh_flags) & 0x4) /* SHF_EXECINSTR */
265
+	    cli_dbgmsg("ELF: Section contains executable code\n");
266
+
267
+	cli_dbgmsg("------------------------------------\n");
268
+    }
269
+
270
+    free(section_hdr);
271
+    return CL_CLEAN;
272
+}
0 273
new file mode 100644
... ...
@@ -0,0 +1,60 @@
0
+/*
1
+ *  Copyright (C) 2005 Tomasz Kojm <tkojm@clamav.net>
2
+ *
3
+ *  Header structures based on ELF: Executable and Linkable Format, Portable
4
+ *  Formats Specification, Version 1.1
5
+ *
6
+ *  This program is free software; you can redistribute it and/or modify
7
+ *  it under the terms of the GNU General Public License as published by
8
+ *  the Free Software Foundation; either version 2 of the License, or
9
+ *  (at your option) any later version.
10
+ *
11
+ *  This program is distributed in the hope that it will be useful,
12
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ *  GNU General Public License for more details.
15
+ *
16
+ *  You should have received a copy of the GNU General Public License
17
+ *  along with this program; if not, write to the Free Software
18
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
+ */
20
+
21
+#ifndef __ELF_H
22
+#define __ELF_H
23
+
24
+#include "cltypes.h"
25
+#include "clamav.h"
26
+
27
+struct elf_file_hdr32 {
28
+    unsigned char e_ident[16];
29
+    uint16_t e_type;
30
+    uint16_t e_machine;
31
+    uint32_t e_version;
32
+    uint32_t e_entry;
33
+    uint32_t e_phoff;
34
+    uint32_t e_shoff;
35
+    uint32_t e_flags;
36
+    uint16_t e_ehsize;
37
+    uint16_t e_phentsize;
38
+    uint16_t e_phnum;
39
+    uint16_t e_shentsize;
40
+    uint16_t e_shnum;
41
+    uint16_t e_shstrndx;
42
+};
43
+
44
+struct elf_section_hdr32 {
45
+    uint32_t sh_name;
46
+    uint32_t sh_type;
47
+    uint32_t sh_flags;
48
+    uint32_t sh_addr;
49
+    uint32_t sh_offset;
50
+    uint32_t sh_size;
51
+    uint32_t sh_link;
52
+    uint32_t sh_info;
53
+    uint32_t sh_addralign;
54
+    uint32_t sh_entsize;
55
+};
56
+
57
+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);
58
+
59
+#endif