40
40
#include "matcher.h"
42
static inline uint16_t EC16(uint16_t v, uint8_t c)
47
return ((v >> 8) + (v << 8));
50
static inline uint32_t EC32(uint32_t v, uint8_t c)
55
return ((v >> 24) | ((v & 0x00FF0000) >> 8) | ((v & 0x0000FF00) << 8) | (v << 24));
42
#define EC16(v, conv) (conv ? cbswap16(v) : v)
43
#define EC32(v, conv) (conv ? cbswap32(v) : v)
58
45
static uint32_t cli_rawaddr(uint32_t vaddr, struct elf_program_hdr32 *ph, uint16_t phnum, uint8_t conv, uint8_t *err)
76
63
return vaddr - EC32(ph[i].p_vaddr, conv) + EC32(ph[i].p_offset, conv);
79
int cli_scanelf(int desc, cli_ctx *ctx)
66
int cli_scanelf(cli_ctx *ctx)
81
68
struct elf_file_hdr32 file_hdr;
82
69
struct elf_section_hdr32 *section_hdr;
84
71
uint16_t shnum, phnum, shentsize, phentsize;
85
72
uint32_t entry, fentry, shoff, phoff, i;
86
73
uint8_t conv = 0, err;
75
fmap_t *map = *ctx->fmap;
89
78
cli_dbgmsg("in cli_scanelf\n");
91
if(read(desc, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
80
if(fmap_readn(map, &file_hdr, 0, sizeof(file_hdr)) != sizeof(file_hdr)) {
92
81
/* Not an ELF file? */
93
82
cli_dbgmsg("ELF: Can't read file header\n");
102
if(file_hdr.e_ident[4] != 1) {
103
cli_dbgmsg("ELF: 64-bit binaries are not supported (yet)\n");
91
format = file_hdr.e_ident[4];
92
if(format != 1 && format != 2) {
93
cli_dbgmsg("ELF: Unknown ELF class (%u)\n", file_hdr.e_ident[4]);
98
struct elf_file_hdr64 file_hdr64;
99
if(fmap_readn(map, &file_hdr64, 0, sizeof(file_hdr64)) != sizeof(file_hdr64)) {
100
/* Not an ELF file? */
101
cli_dbgmsg("ELF: Can't read file header\n");
104
/* it's enough for us to handle ELF64 as 32 */
105
file_hdr.e_entry = file_hdr64.e_entry;
106
file_hdr.e_phoff = file_hdr64.e_phoff;
107
file_hdr.e_shoff = file_hdr64.e_shoff;
108
file_hdr.e_flags = file_hdr64.e_flags;
109
file_hdr.e_ehsize = file_hdr64.e_ehsize;
110
file_hdr.e_phentsize = file_hdr64.e_phentsize;
111
if(file_hdr.e_phentsize == sizeof(struct elf_program_hdr64))
112
file_hdr.e_phentsize = sizeof(struct elf_program_hdr32);
113
file_hdr.e_phnum = file_hdr64.e_phnum;
114
file_hdr.e_shentsize = file_hdr64.e_shentsize;
115
if(file_hdr.e_shentsize == sizeof(struct elf_section_hdr64))
116
file_hdr.e_shentsize = sizeof(struct elf_section_hdr32);
117
file_hdr.e_shnum = file_hdr64.e_shnum;
118
file_hdr.e_shstrndx = file_hdr64.e_shstrndx;
107
121
if(file_hdr.e_ident[5] == 1) {
143
157
switch(EC16(file_hdr.e_machine, conv)) {
144
158
/* Due to a huge list, we only include the most popular machines here */
145
case 0x0: /* EM_NONE */
159
case 0: /* EM_NONE */
146
160
cli_dbgmsg("ELF: Machine type: None\n");
148
case 0x2: /* EM_SPARC */
162
case 2: /* EM_SPARC */
149
163
cli_dbgmsg("ELF: Machine type: SPARC\n");
151
case 0x3: /* EM_386 */
152
166
cli_dbgmsg("ELF: Machine type: Intel 80386\n");
154
case 0x4: /* EM_68K */
155
169
cli_dbgmsg("ELF: Machine type: Motorola 68000\n");
157
case 0x8: /* EM_MIPS */
171
case 8: /* EM_MIPS */
158
172
cli_dbgmsg("ELF: Machine type: MIPS RS3000\n");
160
case 0x15: /* EM_PARISC */
174
case 9: /* EM_S370 */
175
cli_dbgmsg("ELF: Machine type: IBM System/370\n");
177
case 15: /* EM_PARISC */
161
178
cli_dbgmsg("ELF: Machine type: HPPA\n");
163
case 0x20: /* EM_PPC */
180
case 20: /* EM_PPC */
164
181
cli_dbgmsg("ELF: Machine type: PowerPC\n");
166
case 0x21: /* EM_PPC64 */
183
case 21: /* EM_PPC64 */
167
184
cli_dbgmsg("ELF: Machine type: PowerPC 64-bit\n");
169
case 0x22: /* EM_S390 */
186
case 22: /* EM_S390 */
170
187
cli_dbgmsg("ELF: Machine type: IBM S390\n");
172
case 0x40: /* EM_ARM */
189
case 40: /* EM_ARM */
173
190
cli_dbgmsg("ELF: Machine type: ARM\n");
175
case 0x41: /* EM_FAKE_ALPHA */
192
case 41: /* EM_FAKE_ALPHA */
176
193
cli_dbgmsg("ELF: Machine type: Digital Alpha\n");
178
case 0x43: /* EM_SPARCV9 */
195
case 43: /* EM_SPARCV9 */
179
196
cli_dbgmsg("ELF: Machine type: SPARC v9 64-bit\n");
181
case 0x50: /* EM_IA_64 */
198
case 50: /* EM_IA_64 */
182
199
cli_dbgmsg("ELF: Machine type: IA64\n");
201
case 62: /* EM_X86_64 */
202
cli_dbgmsg("ELF: Machine type: AMD x86-64\n");
185
cli_dbgmsg("ELF: Machine type: Unknown (%d)\n", EC16(file_hdr.e_machine, conv));
205
cli_dbgmsg("ELF: Machine type: Unknown (0x%x)\n", EC16(file_hdr.e_machine, conv));
188
208
entry = EC32(file_hdr.e_entry, conv);
195
215
cli_dbgmsg("ELF: Suspicious number of program headers\n");
196
216
if(DETECT_BROKEN) {
198
*ctx->virname = "Broken.Executable";
199
return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
218
*ctx->virname = "Heuristics.Broken.Executable";
201
221
return CL_EFORMAT;
208
228
cli_dbgmsg("ELF: phentsize != sizeof(struct elf_program_hdr32)\n");
209
229
if(DETECT_BROKEN) {
211
*ctx->virname = "Broken.Executable";
212
return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
231
*ctx->virname = "Heuristics.Broken.Executable";
214
234
return CL_EFORMAT;
217
237
phoff = EC32(file_hdr.e_phoff, conv);
218
238
cli_dbgmsg("ELF: Program header table offset: %d\n", phoff);
219
if((uint32_t) lseek(desc, phoff, SEEK_SET) != phoff) {
222
*ctx->virname = "Broken.Executable";
223
return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
228
240
program_hdr = (struct elf_program_hdr32 *) cli_calloc(phnum, phentsize);
229
241
if(!program_hdr) {
234
246
cli_dbgmsg("------------------------------------\n");
236
248
for(i = 0; i < phnum; i++) {
238
if(read(desc, &program_hdr[i], sizeof(struct elf_program_hdr32)) != sizeof(struct elf_program_hdr32)) {
251
if(fmap_readn(map, &program_hdr[i], phoff, sizeof(struct elf_program_hdr32)) != sizeof(struct elf_program_hdr32))
253
phoff += sizeof(struct elf_program_hdr32);
255
struct elf_program_hdr64 program_hdr64;
257
if(fmap_readn(map, &program_hdr64, phoff, sizeof(program_hdr64)) != sizeof(program_hdr64)) {
260
program_hdr[i].p_type = program_hdr64.p_type;
261
program_hdr[i].p_offset = program_hdr64.p_offset;
262
program_hdr[i].p_vaddr = program_hdr64.p_vaddr;
263
program_hdr[i].p_paddr = program_hdr64.p_paddr;
264
program_hdr[i].p_filesz = program_hdr64.p_filesz;
265
program_hdr[i].p_memsz = program_hdr64.p_memsz;
266
program_hdr[i].p_flags = program_hdr64.p_flags;
267
program_hdr[i].p_align = program_hdr64.p_align;
269
phoff += sizeof(program_hdr64);
239
273
cli_dbgmsg("ELF: Can't read segment #%d\n", i);
240
274
cli_dbgmsg("ELF: Possibly broken ELF file\n");
241
275
free(program_hdr);
242
276
if(DETECT_BROKEN) {
244
*ctx->virname = "Broken.Executable";
245
return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
278
*ctx->virname = "Heuristics.Broken.Executable";
262
296
cli_dbgmsg("ELF: Can't calculate file offset of entry point\n");
263
297
if(DETECT_BROKEN) {
265
*ctx->virname = "Broken.Executable";
266
return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
299
*ctx->virname = "Heuristics.Broken.Executable";
268
302
return CL_EFORMAT;
279
313
cli_dbgmsg("ELF: Suspicious number of sections\n");
280
314
if(DETECT_BROKEN) {
282
*ctx->virname = "Broken.Executable";
283
return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
316
*ctx->virname = "Heuristics.Broken.Executable";
285
319
return CL_EFORMAT;
290
324
cli_dbgmsg("ELF: shentsize != sizeof(struct elf_section_hdr32)\n");
291
325
if(DETECT_BROKEN) {
293
*ctx->virname = "Broken.Executable";
294
return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
327
*ctx->virname = "Heuristics.Broken.Executable";
296
330
return CL_EFORMAT;
299
333
shoff = EC32(file_hdr.e_shoff, conv);
300
334
cli_dbgmsg("ELF: Section header table offset: %d\n", shoff);
301
if((uint32_t) lseek(desc, shoff, SEEK_SET) != shoff) {
302
/* Possibly broken end of file */
305
*ctx->virname = "Broken.Executable";
306
return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
311
336
section_hdr = (struct elf_section_hdr32 *) cli_calloc(shnum, shentsize);
312
337
if(!section_hdr) {
317
342
cli_dbgmsg("------------------------------------\n");
319
344
for(i = 0; i < shnum; i++) {
321
if(read(desc, §ion_hdr[i], sizeof(struct elf_section_hdr32)) != sizeof(struct elf_section_hdr32)) {
347
if(fmap_readn(map, §ion_hdr[i], shoff, sizeof(struct elf_section_hdr32)) != sizeof(struct elf_section_hdr32))
349
shoff += sizeof(struct elf_section_hdr32);
351
struct elf_section_hdr64 section_hdr64;
353
if(fmap_readn(map, §ion_hdr64, shoff, sizeof(section_hdr64)) != sizeof(section_hdr64)) {
356
section_hdr[i].sh_name = section_hdr64.sh_name;
357
section_hdr[i].sh_type = section_hdr64.sh_type;
358
section_hdr[i].sh_flags = section_hdr64.sh_flags;
359
section_hdr[i].sh_addr = section_hdr64.sh_addr;
360
section_hdr[i].sh_offset = section_hdr64.sh_offset;
361
section_hdr[i].sh_size = section_hdr64.sh_size;
362
section_hdr[i].sh_link = section_hdr64.sh_link;
363
section_hdr[i].sh_info = section_hdr64.sh_info;
364
section_hdr[i].sh_addralign = section_hdr64.sh_addralign;
365
section_hdr[i].sh_entsize = section_hdr64.sh_entsize;
367
shoff += sizeof(section_hdr64);
322
371
cli_dbgmsg("ELF: Can't read section header\n");
323
372
cli_dbgmsg("ELF: Possibly broken ELF file\n");
324
373
free(section_hdr);
325
374
if(DETECT_BROKEN) {
327
*ctx->virname = "Broken.Executable";
328
return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
376
*ctx->virname = "Heuristics.Broken.Executable";
409
int cli_elfheader(int desc, struct cli_exe_info *elfinfo)
458
int cli_elfheader(fmap_t *map, struct cli_exe_info *elfinfo)
411
460
struct elf_file_hdr32 file_hdr;
412
461
struct elf_section_hdr32 *section_hdr;
414
463
uint16_t shnum, phnum, shentsize, phentsize, i;
415
464
uint32_t entry, fentry = 0, shoff, phoff;
416
465
uint8_t conv = 0, err;
419
468
cli_dbgmsg("in cli_elfheader\n");
421
if(read(desc, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
470
if(fmap_readn(map, &file_hdr, 0, sizeof(file_hdr)) != sizeof(file_hdr)) {
422
471
/* Not an ELF file? */
423
472
cli_dbgmsg("ELF: Can't read file header\n");
432
if(file_hdr.e_ident[4] != 1) {
433
cli_dbgmsg("ELF: 64-bit binaries are not supported (yet)\n");
481
format = file_hdr.e_ident[4];
482
if(format != 1 && format != 2) {
483
cli_dbgmsg("ELF: Unknown ELF class (%u)\n", file_hdr.e_ident[4]);
488
struct elf_file_hdr64 file_hdr64;
489
if(!fmap_readn(map, &file_hdr64, 0, sizeof(file_hdr64)) != sizeof(file_hdr64)) {
490
/* Not an ELF file? */
491
cli_dbgmsg("ELF: Can't read file header\n");
494
/* it's enough for us to handle ELF64 as 32 */
495
file_hdr.e_entry = file_hdr64.e_entry;
496
file_hdr.e_phoff = file_hdr64.e_phoff;
497
file_hdr.e_shoff = file_hdr64.e_shoff;
498
file_hdr.e_flags = file_hdr64.e_flags;
499
file_hdr.e_ehsize = file_hdr64.e_ehsize;
500
file_hdr.e_phentsize = file_hdr64.e_phentsize;
501
if(file_hdr.e_phentsize == sizeof(struct elf_program_hdr64))
502
file_hdr.e_phentsize = sizeof(struct elf_program_hdr32);
503
file_hdr.e_phnum = file_hdr64.e_phnum;
504
file_hdr.e_shentsize = file_hdr64.e_shentsize;
505
if(file_hdr.e_shentsize == sizeof(struct elf_section_hdr64))
506
file_hdr.e_shentsize = sizeof(struct elf_section_hdr32);
507
file_hdr.e_shnum = file_hdr64.e_shnum;
508
file_hdr.e_shstrndx = file_hdr64.e_shstrndx;
437
511
if(file_hdr.e_ident[5] == 1) {
438
512
#if WORDS_BIGENDIAN == 1
461
535
phoff = EC32(file_hdr.e_phoff, conv);
462
if((uint32_t) lseek(desc, phoff, SEEK_SET) != phoff) {
466
537
program_hdr = (struct elf_program_hdr32 *) cli_calloc(phnum, phentsize);
467
538
if(!program_hdr) {
472
543
for(i = 0; i < phnum; i++) {
473
if(read(desc, &program_hdr[i], sizeof(struct elf_program_hdr32)) != sizeof(struct elf_program_hdr32)) {
546
if(fmap_readn(map, &program_hdr[i], phoff, sizeof(struct elf_program_hdr32)) != sizeof(struct elf_program_hdr32))
548
phoff += sizeof(struct elf_program_hdr32);
550
struct elf_program_hdr64 program_hdr64;
552
if(fmap_readn(map, &program_hdr64, phoff, sizeof(program_hdr64)) != sizeof(program_hdr64)) {
555
program_hdr[i].p_type = program_hdr64.p_type;
556
program_hdr[i].p_offset = program_hdr64.p_offset;
557
program_hdr[i].p_vaddr = program_hdr64.p_vaddr;
558
program_hdr[i].p_paddr = program_hdr64.p_paddr;
559
program_hdr[i].p_filesz = program_hdr64.p_filesz;
560
program_hdr[i].p_memsz = program_hdr64.p_memsz;
561
program_hdr[i].p_flags = program_hdr64.p_flags;
562
program_hdr[i].p_align = program_hdr64.p_align;
564
phoff += sizeof(program_hdr64);
474
568
cli_dbgmsg("ELF: Can't read segment #%d\n", i);
475
569
free(program_hdr);
503
597
shoff = EC32(file_hdr.e_shoff, conv);
504
if((uint32_t) lseek(desc, shoff, SEEK_SET) != shoff) {
505
/* Possibly broken end of file */
509
599
elfinfo->section = (struct cli_exe_section *) cli_calloc(elfinfo->nsections, sizeof(struct cli_exe_section));
510
600
if(!elfinfo->section) {
523
613
for(i = 0; i < shnum; i++) {
525
if(read(desc, §ion_hdr[i], sizeof(struct elf_section_hdr32)) != sizeof(struct elf_section_hdr32)) {
616
if(fmap_readn(map, §ion_hdr[i], shoff, sizeof(struct elf_section_hdr32)) != sizeof(struct elf_section_hdr32))
618
shoff += sizeof(struct elf_section_hdr32);
620
struct elf_section_hdr64 section_hdr64;
622
if(fmap_readn(map, §ion_hdr64, shoff, sizeof(section_hdr64)) != sizeof(section_hdr64)) {
625
section_hdr[i].sh_name = section_hdr64.sh_name;
626
section_hdr[i].sh_type = section_hdr64.sh_type;
627
section_hdr[i].sh_flags = section_hdr64.sh_flags;
628
section_hdr[i].sh_addr = section_hdr64.sh_addr;
629
section_hdr[i].sh_offset = section_hdr64.sh_offset;
630
section_hdr[i].sh_size = section_hdr64.sh_size;
631
section_hdr[i].sh_link = section_hdr64.sh_link;
632
section_hdr[i].sh_info = section_hdr64.sh_info;
633
section_hdr[i].sh_addralign = section_hdr64.sh_addralign;
634
section_hdr[i].sh_entsize = section_hdr64.sh_entsize;
636
shoff += sizeof(section_hdr64);
640
cli_dbgmsg("ELF: Can't read section header\n");
526
641
free(section_hdr);
527
642
free(elfinfo->section);
528
643
elfinfo->section = NULL;
532
646
elfinfo->section[i].rva = EC32(section_hdr[i].sh_addr, conv);
533
647
elfinfo->section[i].raw = EC32(section_hdr[i].sh_offset, conv);
534
648
elfinfo->section[i].rsz = EC32(section_hdr[i].sh_size, conv);