miércoles, 20 de febrero de 2013

CURSO-5


        Contaminando ficheros EXE
       ---------------------------


       Los ficheros com no parecen un problema, pero ¿y los EXE?,
no son ni mucho menos difíciles de contaminar aunque hay que dominar
el header (la cabecera) de los EXE.
       Los EXEs pueden tener más de un segmento lo que hace necesario
una cabecera con información acerca de la memoria que necesitará  el
programa, la dirección de inicio donde se comenzará  a ejecutar el
programa etc. Además posee una tabla de realocación para que el
programa se pueda cargar a partir de cualquier segmento de memoria.
      Cuando el DOS carga un EXE primero constuye un PSP y un
environment block (como ya hac¡a con los COM) luego lee el header
y a partir de los datos de éste carga el EXE. Luego realocatea el
código.¿Pero qué coño es eso de realocatear el código?.
     En un Exe las referencias de segmento se hacen a partir del
segmento 0 pero el código no tiene porqué cargarse necesáriamente
en ese segmento por eso se creó la realocación. En el Exe se
almacena una tabla con punteros a todas las referencias a segmentos
ya sabéis, instrucciones del tipo.

     call 1234:0023   (ojo que un call 23 no hace referencia a segmentos)
     jmp  1000:2344

     nuestro virus no tendrá  referencias de segmentos ya que será
     menor que 65000 bytes (espero je,je,je) ,excepto el salto
     al cs:ip inicial del exe. pero esa dirección la realocatearemos
     manualmente >:)

     En el Exe se almacena una lista de punteros que indican donde
hay referencias de segmento . Pero ojo que estas referencias tampoco
estan realocateadas por lo que el DOS suma a cada puntero. El segmento
efectivo donde se cargó el EXE + 10 (tamaño del PSP).Ahora tenemos
la dirección real donde hay una referencia de segmento y el DOS
realocatea la dirección sumando la dirección efectiva + 10.
Después de hacer esto con cada puntero de la tabla de realocación
el Dos tendrá  en memoria el código con la dirección que toca
para cada segmento.
   

EXE PROGRAM FILE
  Header                                CS:IP (Header)  0000:0000 +
  (relocation                           Eff. Segment    1000      +
   table entries=2)                     PSP             0010      =
                                        -------------------------
                                        Entry Point     1010:0000
  Relocation Table    
   0000:0003                                                                               + 1010H = 1010:0003
                                 
   0000:0007                                                                               + 1010H = 1010:0007
                               
  Program Image                        PROGRAM IN MEMORY                  
                                        PSP                     1000:0000  
  call 0001:0000                        call 1011:0000          1010:0000
  nop                                   nop                     1010:0005
  mov ax, 0003                          mov ax, 1013            1010:0006
  mov ds, ax                            mov ds, ax              1010:0009

  Aqu¡ tenéis la estructura del header de los EXE.
 
   Offset Descripcion
     00   Marca de EXE (MZ = 4D5A)
     02   Numero de bytes en la ultima pagina (de 512 bytes) del programa
     04   Numero total de paginas de 512 bytes, redondeado hacia arriba
     06   Numero de entradas en la Tabla de Alocacion
     08   Size del header (en paragrafos, incluyendo la Tabla de realocacion)
     0A   Minimo de memoria requerido (en para)
     0C   Maximo de memoria requerido (en para)
     0E   SS inicial
     10   SP inicial
     12   Checksum
     14   IP inicial
     16   CS inicial
     18   Offset de la Tabla de Alocacion desde el comienzo del file
     1A   Numero de Overlays generados


 En 00 tenemos la marca de los EXE que es MZ (es lo que diferencia un
 exe de un com)
 Si os fijáis con las entradas 04 y 06 tenemos el tamaño del EXE.
 (pages)*512+reminder.S¡ lo sé es una manera muy rebuscada de poner
 el tamaño lo pod¡an haber puesto directamente con esos 4 bytes ,pero
 bueno as¡ hay m s emoción je,je,je.En 06 tenemos el número de punteros
 de la tabla de realoción (Cada puntero ocupa 4 bytes con lo que
 4*nº de punteros nos dar  el tamaño de la tabla de realocación)
 En 08 el tamaño del header en paragrafos (incluyendo la tabla de
 realocación).
 Después tenemos el Minimo y m ximo de memoria también en par grafo
 En los Exes al ocupar m s de un segmento no es posible cargar la
 pila desde la dirección FFFFh como hac¡amos en los com hemos de
 indicar en el header donde queremos que esté la pila. Por lo
 que hay dos entradas de dos bytes cada una con el segmento
 y el offset para la pila.
 En el offset 12 tenemos el checksum. Normalmente está  a 0 con lo
 que lo podemos utilizar para marcar el archivo como contaminado.
 El los offset 14 y 16 el IP y CS inicial (comienzo de la ejecución).
 En el offset 18 el offset de comienzo de la tabla de realocación
 normalmente es 1c es decir 28 en decimal.
 Si os fijáis normalmente 4*nº de punteros de la tabla de realocación
 + offset tabla de realocación = paras del header * 16
 Pero esto no siempre es igual ya que tenemos que poner el header en
 parágrafos y no siempre la cabecera + la tabla de realocación nos
 dan un múltipo de 16 con lo que normalemente tendremos de 1 a 15 bytes
 de basura en el file,después de la tabla de realocación (que también
 se podr¡an utilizar para marcar el file como infectado).
 En 1a se menciona el número de overlays generados , hay programas
 que por su gran tamaño no se pueden cargar enteros en memoria
 por lo que hay que cargarlos poco a poco mediante overlays internos
 (carece de utilidad en esta lección  :<) Antes de comenzar con la teoría sobre infección de EXE's me gustar¡a

 hablar un poco de como se direcciona la memoria.

 Como todos ya sabéis en un 8086 la memoria se direcciona con 2 registros

 de 16 bits cada uno. Uno que direcciona un segmento (o bloque de FFFFh bytes)

 y otro que direcciona una posición dentro de dicho segmento).

 Pero resulta que el 8086 no ten¡a un bus de datos de 32 bits sino de 20

 entonces tuvieron que armar una pirula para que entrase la dirección en

 el bus. Inventaron la segmentación de memoria.

 Teniendo en cuenta que tenemos 4 bytes para apuntar a una dirección de

 memoria en teoría podríamos direccionar 4 gigas de memoria. Pero con

 un bus de 20 bits eso no es posible  ya que 2^20 solo nos permite

 direccionar 1 mega de memoria.

 Bueno, bueno, que chapuzas pero ¿como calcular una dirección de 20 bits

 si sólo tengo registros de 16 bits?. Bueno aquí viene lo divertido.

 El segmento lo multiplica por 16 o lo que es lo mismo desplaza hacia

 la izquierda 4 bits el registro de segmento y al resultado se le suma

 el registro del offset con esto obtenemos la dirección f¡sica

 deseada, una dirección de 20 bits.

   Tened en cuenta que éste método es el causante de que tengamos los

 famoso 640 bytes de memoria convencional. El mega que podemos direccionar

 es separado en memoria convencional y en memoria superior que va de los

 640 bytes al mega.La memoria convencional se utiliza para cargar el kernel

 del DOS ,los vectores de interrupcion,programas residentes,

 programas de usuario etc. y la superior para memoria de video,

 tablas del bios etc.

 Lógicamente eso no quiere decir que no podamos utilizar memoria por encima

 del mega.En la memoria superior siempre quedan segmentos inutilizados

 que gracias a drivers de memoria pueden convertirse en los denominados

 UMB (upper memory blocks, bloques de memoria superior). Estos están

 dentro del mega direccionable por el DOS pero en realidad en ellos hay

 programas y datos almacenados en memoria extendida y que son transladados

 a la memoria convencional para su ejecución y su posible direccionamiento.



 Bueno en refinitiva teniendo una dirección como esta 1234h:3423h

 la dirección real ser¡a 12340h+3223h=15563h



 Ahora supongo que ya sabréis la razón de reservar memoria en parágrafos

 ¿porqué 16 bytes y no reservar memoria en bytes?.Es obvio. 16 es la

 diferencia entre un segmento y el siguiente. La diferencia entre 1000:0000

 y 1001:0000 no son FFFFh bytes como algunos suponías son 16 bytes. ;'>
 que són la unidad mínima de memoria que se puede reservar.
 S¡,s¡ de aqu¡ viene el número mágico je,je.
 Ahora supongo ,entenderéis mejor la residencia. En la residencia
 buscamos el segmento del MCB disminuyendo el segmento donde está  el PSP
 Con esto no nos vamos FFFFh bytes hacia atrás sino que sólo nos vamos
 16 bytes que es lo que ocupa el MCB (je,je,je,je ,apasionante ¿no?)

 Pasos para infectar un archivo EXE
 ----------------------------------

 1. Leemos el header a un área de memoria para poder modificarlo a placer.
    Calculamos el tamaño del archivo.
    Y calculamos el CS:IP que dever  tener el header (para que apunte
    al código del virus que situo al final del archivo).
    Puedes poner de 1-15 bytes de basura en el archivo para redondearlo
    a parágrafo esto hace que la ip sea 0 (invariante) siempre y te
    ahorras tener que calcular el desplazamiento que sufrirán las variables
    (como hac¡amos en los archivos com).
    Tén en cuenta que si utilizas dir stealth (técnica que evita que se vea
    un incremento del tamaño en los archivos contaminados ,necesitás saber
    el tamaño exacto del archivo) al poner de 1-15 bytes de basura el
    stealth te se irá  de 1 a 15 bytes por lo que podrías redondearlo a un
    número fijo poniendo luego basura después del virus  :>.

 2. Copiamos el virus al final . Espero que no tengas problemas en hacer
    esto, sino despídete.

 3. Calculamos el SS:SP. El virus logicamente se tendrá que buscar un
    sitio para tener la stack. Esto es ,porque si el programa tenía la
    stack sobre el código del virus ,podría sobreescribirlo mientras
    lo ejecutamos y te aseguro que eso no es bueno para nuestro virus
    creetelo.:>

 4. Calcular el nuevo tamaño que tendrá  el archivo.Esto no es dif¡cil
    simplemente buscamos el tamaño del archivo (ten en cuenta que ya
    tenemos el código del virus al final ) y dividimos por 512
    el resulatado incrementado en 1 ser  el número de páginas
    y el resto el reminder.

 5. Calculamos la memoria mínima que necesitará  el programa.
    Simplemente sumamos el tamaño en parágrafos del virus.
    a la memoria m¡nima.

 6. Escribimos el nuevo header en el archivo.
    (En el código del virus almacenamos el antiguo CS:IP y el SS:IP
     para devolver el control al HOSTE)

 NOTA: Al cargar un archivo EXE DS y ES apuntan al PSP ,SS y CS pueden
       ser diferentes.Ojo con lo que hacéis con DS y ES porqué los
       necesitaréis luego para dar el control al HOSTE.(realocatear el salto
       de vuelta al hoste).
     

           Text of NIGROMANTE .

           nEUrOtIc cpU. is with you.

0 comentarios:

Publicar un comentario