SHARE
TWEET

Untitled

a guest Apr 5th, 2012 86 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  *    Recuperación del código tras una inyección segmentada.
  3.  *    Copyright (C) 2012  Gonzalo J. Carracedo
  4.  *
  5.  *    This program is free software: you can redistribute it and/or modify
  6.  *    it under the terms of the GNU General Public License as published by
  7.  *    the Free Software Foundation, either version 3 of the License, or
  8.  *    (at your option) any later version.
  9.  *
  10.  *    This program is distributed in the hope that it will be useful,
  11.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *    GNU General Public License for more details.
  14.  *
  15.  *    You should have received a copy of the GNU General Public License
  16.  *    along with this program.  If not, see <http://www.gnu.org/licenses/>
  17.  */
  18.  
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <elf.h>
  22. #include <sys/types.h>
  23. #include <sys/syscall.h>
  24. #include <unistd.h>
  25. #include <fcntl.h>
  26. #include <sys/mman.h>
  27.  
  28. #define BOTTOM_MARKER      0x5841504b
  29. #define TOP_MARKER         BOTTOM_MARKER
  30.  
  31. #define GET_FILE_SIZE(fd, size)                                \
  32.   asm volatile ("xchg %%ebx, %%esi\n"                          \
  33.                 "int $0x80\n"                                  \
  34.                 "xchg %%ebx, %%esi\n" : "=a" (size) :          \
  35.                 "a" (__NR_lseek), "S" (fd), "c" (0), "d" (2));
  36.                
  37. void *
  38. map_elf (const char *path, size_t *size)
  39. {
  40.   int fd;
  41.   void *map;
  42.   Elf32_Ehdr *Ehdr;
  43.  
  44.   if ((fd = open (path, O_RDWR)) < 0)
  45.   {
  46.     perror (path);
  47.     return NULL; /* Error al abrir */
  48.   }
  49.  
  50.   GET_FILE_SIZE (fd, *size);
  51.  
  52.   if (*size < 0)
  53.     return NULL;
  54.    
  55.   if ((uint32_t) (map = mmap (NULL, *size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) & 0xfff)
  56.   {
  57.     perror ("mmap");
  58.     close (fd);
  59.     return NULL;
  60.   }
  61.  
  62.   close (fd);
  63.  
  64.   Ehdr = (Elf32_Ehdr *) map;
  65.  
  66.  
  67.   if (Ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
  68.       Ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
  69.       Ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
  70.       Ehdr->e_ident[EI_MAG3] != ELFMAG3 ||
  71.       Ehdr->e_ident[EI_CLASS] != ELFCLASS32 ||
  72.       Ehdr->e_ident[EI_DATA] != ELFDATA2LSB ||
  73.       Ehdr->e_type != ET_EXEC && Ehdr->e_type != ET_DYN)
  74.   {
  75.     munmap (map, *size);
  76.     return NULL; /* Números mágicos incorrectos */
  77.   }
  78.  
  79.   return map;
  80. }
  81.  
  82. int
  83. find_code_segment (void *image_base, void **start, size_t *size)
  84. {
  85.   int i, code_idx;
  86.   off_t   gap_start, gap_start_relative;
  87.  
  88.   Elf32_Ehdr *Ehdr;
  89.   Elf32_Phdr *Phdr;
  90.  
  91.   code_idx = -1;
  92.  
  93.   Ehdr = (Elf32_Ehdr *) image_base;
  94.   Phdr = (Elf32_Phdr *) (image_base + Ehdr->e_phoff);
  95.    
  96.   for (i = 0; i < Ehdr->e_phnum; i++)
  97.   {  
  98.     if (Phdr[i].p_type == PT_LOAD)
  99.     {
  100.       if (Phdr[i].p_flags & PF_X)
  101.       {
  102.         if (code_idx != -1) /* ¿Dos segmentos de código? dew */
  103.           return -1;
  104.         code_idx = i;
  105.       }
  106.     }
  107.   }
  108.    
  109.   if (code_idx == -1)
  110.     return -1;
  111.    
  112.   *start = image_base + Phdr[code_idx].p_offset;
  113.   *size  = Phdr[code_idx].p_filesz;
  114.  
  115.   return 0;
  116. }
  117.  
  118.  
  119. void *
  120. find_contiguous_part (void *start, size_t size)
  121. {
  122.   uint32_t *code_as_dwords;
  123.   size_t   code_dwords;
  124.   int i;
  125.  
  126.   code_dwords = size >> 2;
  127.   code_as_dwords = (uint32_t *) start;
  128.  
  129.   for (i = 0; i < code_dwords; i++)
  130.     if (code_as_dwords[i] == BOTTOM_MARKER)
  131.       return (void *) &code_as_dwords[i];
  132.      
  133.   return NULL;
  134. }
  135.  
  136. int
  137. in_bounds (void *code_base, void *contiguous, uint32_t offset)
  138. {
  139.   if ((uint32_t) contiguous - offset < (uint32_t) code_base)
  140.     return 0;
  141.  
  142.   return 1;
  143. }
  144.  
  145. int
  146. restore_infection (const char *dump_path, void *code_base, void *contiguous)
  147. {
  148.   FILE *fp;
  149.   uint32_t *code_as_dwords;
  150.   code_as_dwords = (uint32_t *) contiguous;
  151.   size_t size;
  152.   uint32_t   offset;
  153.  
  154.   printf ("Tamaño de la parte contigua: %d bytes\n", code_as_dwords[1]);
  155.   printf ("Desplazamiento inverso al siguiente trozo: 0x%x\n", code_as_dwords[2]);
  156.  
  157.   offset = code_as_dwords[2];
  158.  
  159.   if ((fp = fopen (dump_path, "wb")) == NULL)
  160.   {
  161.     perror (dump_path);
  162.     return -1;
  163.   }
  164.  
  165.   if (fwrite (contiguous, code_as_dwords[1], 1, fp) < 1)
  166.   {
  167.     perror ("fwrite contiguous");
  168.     fclose (fp);
  169.     return -1;
  170.   }
  171.  
  172.   while (offset)
  173.   {
  174.     if (!in_bounds (code_base, contiguous, offset))
  175.     {
  176.       printf ("Error: desplazamiento inverso fuera de rango (0x%x)\n", offset);
  177.       fclose (fp);
  178.       return -1;
  179.     }
  180.    
  181.     code_as_dwords = (uint32_t *) (contiguous - offset);
  182.     size = code_as_dwords[0] & 0xff;
  183.     offset = code_as_dwords[0] >> 8;
  184.    
  185.     printf ("NOP chunk: %d bytes, desplazamiento inverso: 0x%x\n", size, offset);
  186.     if (fwrite (&code_as_dwords[1], size, 1, fp) < 1)
  187.     {
  188.       perror ("fwrite chunked");
  189.       fclose (fp);
  190.       return -1;
  191.     }
  192.  
  193.   }
  194.  
  195.   fclose (fp);
  196.   return 0;
  197. }
  198.  
  199. int
  200. main (int argc, char *argv[])
  201. {
  202.   void *base;
  203.   size_t size;
  204.  
  205.   void *code_base;
  206.   size_t code_size;
  207.  
  208.   void *contiguous;
  209.  
  210.   FILE *fp;
  211.  
  212.   if (argc != 3)
  213.   {
  214.     fprintf (stderr, "Uso: %s <infected binary> <output>\n", argv[0]);
  215.     return 1;
  216.   }
  217.  
  218.   if ((base = map_elf (argv[1], &size)) == NULL)
  219.   {
  220.     fprintf (stderr, "%s: %s: imposible mapear\n", argv[0], argv[1]);
  221.     return 1;
  222.   }
  223.  
  224.   if (find_code_segment (base, &code_base, &code_size) == -1)
  225.   {
  226.     fprintf (stderr, "%s: %s: no se pudo encontrar un segmento de código adecuado\n", argv[0], argv[1]);
  227.     return 1;
  228.   }
  229.  
  230.   if ((contiguous = find_contiguous_part (code_base, code_size)) == NULL)
  231.   {
  232.     fprintf (stderr, "%s: %s: el binario no está infectado\n", argv[0], argv[1]);
  233.     return 1;
  234.   }
  235.  
  236.   printf ("El binario está infectdo:\n");
  237.   return !!restore_infection (argv[2], code_base, contiguous);
  238. }
RAW Paste Data
Top