Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Recuperación del código tras una inyección segmentada.
- * Copyright (C) 2012 Gonzalo J. Carracedo
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <elf.h>
- #include <sys/types.h>
- #include <sys/syscall.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/mman.h>
- #define BOTTOM_MARKER 0x5841504b
- #define TOP_MARKER BOTTOM_MARKER
- #define GET_FILE_SIZE(fd, size) \
- asm volatile ("xchg %%ebx, %%esi\n" \
- "int $0x80\n" \
- "xchg %%ebx, %%esi\n" : "=a" (size) : \
- "a" (__NR_lseek), "S" (fd), "c" (0), "d" (2));
- void *
- map_elf (const char *path, size_t *size)
- {
- int fd;
- void *map;
- Elf32_Ehdr *Ehdr;
- if ((fd = open (path, O_RDWR)) < 0)
- {
- perror (path);
- return NULL; /* Error al abrir */
- }
- GET_FILE_SIZE (fd, *size);
- if (*size < 0)
- return NULL;
- if ((uint32_t) (map = mmap (NULL, *size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) & 0xfff)
- {
- perror ("mmap");
- close (fd);
- return NULL;
- }
- close (fd);
- Ehdr = (Elf32_Ehdr *) map;
- if (Ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
- Ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
- Ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
- Ehdr->e_ident[EI_MAG3] != ELFMAG3 ||
- Ehdr->e_ident[EI_CLASS] != ELFCLASS32 ||
- Ehdr->e_ident[EI_DATA] != ELFDATA2LSB ||
- Ehdr->e_type != ET_EXEC && Ehdr->e_type != ET_DYN)
- {
- munmap (map, *size);
- return NULL; /* Números mágicos incorrectos */
- }
- return map;
- }
- int
- find_code_segment (void *image_base, void **start, size_t *size)
- {
- int i, code_idx;
- off_t gap_start, gap_start_relative;
- Elf32_Ehdr *Ehdr;
- Elf32_Phdr *Phdr;
- code_idx = -1;
- Ehdr = (Elf32_Ehdr *) image_base;
- Phdr = (Elf32_Phdr *) (image_base + Ehdr->e_phoff);
- for (i = 0; i < Ehdr->e_phnum; i++)
- {
- if (Phdr[i].p_type == PT_LOAD)
- {
- if (Phdr[i].p_flags & PF_X)
- {
- if (code_idx != -1) /* ¿Dos segmentos de código? dew */
- return -1;
- code_idx = i;
- }
- }
- }
- if (code_idx == -1)
- return -1;
- *start = image_base + Phdr[code_idx].p_offset;
- *size = Phdr[code_idx].p_filesz;
- return 0;
- }
- void *
- find_contiguous_part (void *start, size_t size)
- {
- uint32_t *code_as_dwords;
- size_t code_dwords;
- int i;
- code_dwords = size >> 2;
- code_as_dwords = (uint32_t *) start;
- for (i = 0; i < code_dwords; i++)
- if (code_as_dwords[i] == BOTTOM_MARKER)
- return (void *) &code_as_dwords[i];
- return NULL;
- }
- int
- in_bounds (void *code_base, void *contiguous, uint32_t offset)
- {
- if ((uint32_t) contiguous - offset < (uint32_t) code_base)
- return 0;
- return 1;
- }
- int
- restore_infection (const char *dump_path, void *code_base, void *contiguous)
- {
- FILE *fp;
- uint32_t *code_as_dwords;
- code_as_dwords = (uint32_t *) contiguous;
- size_t size;
- uint32_t offset;
- printf ("Tamaño de la parte contigua: %d bytes\n", code_as_dwords[1]);
- printf ("Desplazamiento inverso al siguiente trozo: 0x%x\n", code_as_dwords[2]);
- offset = code_as_dwords[2];
- if ((fp = fopen (dump_path, "wb")) == NULL)
- {
- perror (dump_path);
- return -1;
- }
- if (fwrite (contiguous, code_as_dwords[1], 1, fp) < 1)
- {
- perror ("fwrite contiguous");
- fclose (fp);
- return -1;
- }
- while (offset)
- {
- if (!in_bounds (code_base, contiguous, offset))
- {
- printf ("Error: desplazamiento inverso fuera de rango (0x%x)\n", offset);
- fclose (fp);
- return -1;
- }
- code_as_dwords = (uint32_t *) (contiguous - offset);
- size = code_as_dwords[0] & 0xff;
- offset = code_as_dwords[0] >> 8;
- printf ("NOP chunk: %d bytes, desplazamiento inverso: 0x%x\n", size, offset);
- if (fwrite (&code_as_dwords[1], size, 1, fp) < 1)
- {
- perror ("fwrite chunked");
- fclose (fp);
- return -1;
- }
- }
- fclose (fp);
- return 0;
- }
- int
- main (int argc, char *argv[])
- {
- void *base;
- size_t size;
- void *code_base;
- size_t code_size;
- void *contiguous;
- FILE *fp;
- if (argc != 3)
- {
- fprintf (stderr, "Uso: %s <infected binary> <output>\n", argv[0]);
- return 1;
- }
- if ((base = map_elf (argv[1], &size)) == NULL)
- {
- fprintf (stderr, "%s: %s: imposible mapear\n", argv[0], argv[1]);
- return 1;
- }
- if (find_code_segment (base, &code_base, &code_size) == -1)
- {
- fprintf (stderr, "%s: %s: no se pudo encontrar un segmento de código adecuado\n", argv[0], argv[1]);
- return 1;
- }
- if ((contiguous = find_contiguous_part (code_base, code_size)) == NULL)
- {
- fprintf (stderr, "%s: %s: el binario no está infectado\n", argv[0], argv[1]);
- return 1;
- }
- printf ("El binario está infectdo:\n");
- return !!restore_infection (argv[2], code_base, contiguous);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement