martes, 15 de marzo de 2011

Detección de información extra en ejecutables por Th3 Sw4sh

Mi amigo Th3 Sw4sh ha realizado un documento donde explica que es y para que se usa la información extra en ejecutables.

A continuación copio la introducción del documento:

La redacción de este documento tiene como fin explicar una forma de lograr detectar información extra no-original de un archivo ejecutable, que bien puede ser la parte binaria de un archivo quizá su información se encuentre encriptada, sumado a otro para luego darle cualquier uso podemos decir posiblemente (Stub – servidor), Técnica utilizada por los actuales “Encriptadores” .

Empezaremos hablando de la utilidad y hablando del aprovechamiento de esta información respecto al malware, mostraré unos cuantos ejemplos y espero de una u otra forma les llegue a ser de ayuda.

El documento y el código fuente en C para realinear secciones y así evitar que sea sencillo localizar esta información extra lo subo por aquí.

Gracias Th3 Sw4sh!

Código para pasar de RVA a Offset

Buenas noches! Es hora de comenzar a programar un poquillo con esto del PE.

Algo que seguro habéis leído en casi todos los documentos que he ido poniendo como referencia es cómo convertir de una dirección relativa virtual, RVA, a una posición física en el fichero, llamémoslo offset.

Primero manualmente

Lo primero que debemos hacer es encontrar a que sección del ejecutable pertenece esa RVA, para ello en cada sección nos fijamos en los valores VirtualAddress y VirtualSize. Una vez localizada la sección restamos a la RVA la VirtualAddress para saber el desplazamiento dentro de la sección y por último sumamos el PointerToRawData para localizar ese desplazamiento en disco.

Veámoslo con un ejemplo que sino no se entiende nada. Tomemos como ejemplo este post: http://el-blog-de-thor.blogspot.com/2011/03/localizar-direcciones-en-la-iat-mano-12.html

En él buscábamos la IT en disco, mediante un editor hexadecimal vimos que esta se encontraba en la RVA 0x7604. Mirando la secciones nos encontramos con la primera, .text con los siguientes valores:

Name: .text VirtualSize: 0x7748 VirtualAddress: 0x1000 SizeOfRawData: 0x7800 PointerToRawData: 0x400

La sección empieza en 0x1000 y acaba en 0x8748 (0x1000+0x7748), por lo que la RVA 0x7604 se encuentra dentro de ella.

Ahora debemos hacer los cálculos. RVA – comienzo de la sección(VirtualAddress) + comienzo de la sección en disco (PointerToRawData). 0x7604 – 0x1000 + 0x400 = 0x6A04

Y ahí está:

image

A programarlo

Vamos a programarlo en C, al programa se le pasaran 2 parámetros, el primero el nombre del ejecutable y el segundo la RVA en hexadecimal. Para pasar de una cadena en hexadecimal a un número usaremos la función strtoul.

Así que verificamos que lo que nos pasan como argumentos es lo que esperamos:

if(argc != 3 || strtoul(argv[2], NULL, 16) == 0) 
{
printf("Se esperaban 2 parametros, el primero un fichero y el segundo una RVA en hexadecimal\n");  
printf("Ej: %s notepad.exe 3A03\n", argv[0]);  
return EXIT_FAILURE;  
}

Después leemos la RVA recibida, abrimos el fichero y lo leemos entero en un buffer:

 //Convierte la cadena que contiene el numero en hexadecimal a DWORD   
DWORD RVA = strtoul(argv[2], NULL, 16);    
HANDLE fichero = CreateFile((LPCTSTR)argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);    
if(fichero == INVALID_HANDLE_VALUE)    
{    
 printf("Error abriendo el fichero\n");    
 return EXIT_FAILURE;    
}    
//Se lee todo el fichero en buf    
DWORD size = GetFileSize(fichero, NULL);    
byte *buf = (byte *)malloc(size);    
DWORD bytesleidos;    
ReadFile(fichero, buf, size, &bytesleidos, NULL);    
CloseHandle(fichero);    
if (bytesleidos != size)    
{    
 printf("Error leyendo el fichero\n");    
 return EXIT_FAILURE;    
}

Invocamos a la función mágica que convertirá de RVA a Offset, su contenido después.

DWORD Offset = RVAToOffset(buf, RVA);   
if (Offset == -1)    
{    
 printf("No se encontró el offset correspondiente a dicha RVA\n");    
 return EXIT_FAILURE;    
}    
//Se imprime el resultado
printf("RVA:    0x%08x\n", RVA);   
printf("Offset: 0x%08x\n", Offset);
free(buf); 
return EXIT_SUCCESS;  
}

Y ahora la función mágica la que tiene todo lo importante.

//Dada un dirección relativa virtual, RVA, la transforma a una posición exacta en el fichero 
DWORD RVAToOffset(byte *buf, DWORD RVA)  
{  
//Se lee la cabecera DOS que está al principio
PIMAGE_DOS_HEADER pIDH = (PIMAGE_DOS_HEADER)buf;  
//Se lee la cabecera PE, el campo e_lfanew nos indica donde se encuentra dentro del fichero  
PIMAGE_NT_HEADERS pINH = (PIMAGE_NT_HEADERS)&buf[pIDH->e_lfanew];  
//Buscamos a que sección pertenece la RVA para hacer los cálculos correctos  
for(DWORD i = 0; i < pINH->FileHeader.NumberOfSections; i++){  
 //Nos vamos desplazando por las secciones  
 PIMAGE_SECTION_HEADER pISH = (PIMAGE_SECTION_HEADER)&buf[pIDH->e_lfanew + sizeof(IMAGE_NT_HEADERS) + i*sizeof(IMAGE_SECTION_HEADER)];  
 //Si la RVA está dentro del rango  
 if (pISH->VirtualAddress <= RVA && pISH->VirtualAddress + pISH->SizeOfRawData > RVA){  
   //Se realizan los cálculos  
   return RVA - pISH->VirtualAddress + pISH->PointerToRawData;  
 }  
}  
//Si no encuentra en ninguna sección retornamos -1  
return -1;  
}

Admito que así visto el código asusta un poco, con Visual Studio se ve mas bonito:

image

Y así se usa:

image

Cuelgo aquí el .c y el compilado para que lo podáis ver bien, compilar, probar o incluso usar.

El programa en sí no sirve de mucho, pero es algo necesario (pasar de RVA a Offset) para cuando hagamos cosas mas complicadas y así de paso vamos practicando.
Se esperan críticas al código. Un saludo!

domingo, 13 de marzo de 2011

Documentación interesante

En estos días ando leyendo distinta documentación sobre el formato PE, la tabla de importación de los ejecutables, etc…

Os dejo 3 documentos interesantes sobre el tema. El primero trata sobre la estructura del formato PE, explica algo de la tabla de importaciones y de la de exportaciones. 044-ESTUDIO DE LOS ENCABEZADOS PE parte 1 POR SICK TROEN.zip 048-ESTUDIO DE LOS ENCABEZADOS PE parte 2 POR SICK TROEN.zip

En estas 4 “teorias” Ricardo Narvaja explica lo de que es la Import Table, como recomponerla a mano tras haber dumpeado un archivo comprimido con UPX e incluye un script para reparar la IAT. Realmente bueno.
253-IMPORT TABLES A MANO (parte 1).rar
254-IMPORT TABLES A MANO (parte 2).rar
255-IMPORT TABLES A MANO (parte 3).rar
256-IMPORT TABLES A MANO (parte 4).rar
Y el mas interesante y completo de todos es el artículo de la revista Codebreakers “Portable Executable File Format – A Reverse Engineer View” basta con ver el índice:
1 Introduction 2 Basic Structure 3 The DOS Header 4 The PE Header 5 The Data Directory 6 The Section Table 7 The PE File Sections 8 The Export Section 9 The Import Section 10 The Loader 11 Navigating Imports on Disk 12 Adding Code to a PE File 13 Adding Import to an Executable 14 Introduction to Packers 15 Infection of PE Files by Viruses 16 Conclusion 17 Relative Virtual Addressing Explained 18 References & Bibliography 19 Tools Used 20 Appendix: Complete PE Offset Reference
Felices lecturas!

miércoles, 9 de marzo de 2011

Charla interesante en la Rooted sobre virii

El viernes pasado en la RootedCon 2011 Alberto García realizó una presentación que parece muy interesante: Virus, el arte no debería ser negocio. En las diapositivas comenta varias cosas interesantes.

Una de ellas es que la forma mas típica de infectar un ejecutable es añadiendo una nueva sección, cambiando el EP a la nueva sección, ejecutar el código malicioso y mas tarde regresar al EP original. Y otra forma que comenta para que no sea muy evidente que el EP ha sido modificado es poner como primera instrucción un salto a la nueva sección.

También habla de cifrar un ejecutable y que este a su vez cree nuevas copias cifradas con distintas claves o con distintos algoritmos de cifrado para que cada copia del mismo sea diferente.

Otra de las cosas que comenta es utilizar el protocolo DNS o ICMP para controlar los bots y pasar mas desapercibidos a los cortafuegos.

Espero que pronto salga el video de la conferencia para verlo completo.

lunes, 7 de marzo de 2011

Localizar direcciones en la IAT a mano 2/2


Localizar direcciones en la IAT a mano 1/2

En la anterior entrada localizamos la estructura “Directorio de Datos Importados” correspondiente a la DLL User32.dll que contenía los siguientes valores:

image

dwRVAFunctionNameList: 0x00007854 dwUseless1: 0xFFFFFFFF dwUseless2: 0xFFFFFFFF dwRVAModuleName: 0x0000873C dwRVAFunctionAddressList: 0x00001188

Lo primero es recorrer el vector de nombres de las funciones importadas, dwRVAFunctionNameList, hasta encontrar la de MessageBoxW. Está en la dirección RVA 0x7854, que traducida a FileOffset como hicimos en el anterior entrada nos da: 0x7854-0x1000+0x400= 0x6C54

En esa dirección vemos una lista muy larga de punteros:

image

74 punteros, cada uno de ellos es una RVA donde encontrar el nombre de la función importada de la DLL User32.dll. Así que ahora toca un poco de trabajo sucio e ir uno a uno buscando a que nombre llevan. Por ejemplo el primero 0x00008524 que traducido a FileOffset es 0x7924 donde encontramos esto:

image

Los primeros 2 bytes corresponden al ordinal con el que se exporta la funcionen este caso 0xFF, los siguiente bytes corresponden al nombre de la función importada “GetClientRect”. Siguiente este proceso con el resto de punteros llegamos al que está en la posición 0xE0, en el FileOffset 0x6D34 (0x6C54+0x4*0xE0).

image

0x00839A, traducido a FileOffset: 0x779A (0x839A-0x1000+0x400), ahí es donde encontramos lo siguiente:

image

Que es la función buscada.

Sabemos que está en al posición 0xE0 de la lista de funciones importadas de user32.dll. Ahora tenemos que ir a esa posición de la lista de dirección de las funciones, dwRVAFunctionAddressList, y podremos saber en que dirección de memoria dentro de la IAT se encontrará una vez cargado el programa en memoria la dirección en nuestra versión de Windows de la funcion MesageBoxW.

La lista de direcciones se encuentra en al dirección RVA 0x00001188: dwRVAFunctionAddressList: 0x00001188

Sabiendo que la dirección de nuestra función (MessageBoxW) se encontraba en la posición 0xE0 deberemos sumar este valor al comienzo de la lista para obtener su dirección RVA exacta: 0x1188+0xE0=0x1268

Esta recordemos que es la dirección RVA, para obtener la dirección real en memoria debemos de sumarla la “ImageBase”, es un valor de la cabecera PE que en el ejecutable que estamos usando(Notepad de XP SP2 en español) es 0x01000000: 0x01000000+0x1268=0x01001268

Y efectivamente una vez cargado el programa en memoria en esa dirección podemos encontrar la dirección en nuestro sistema de MessageBoxW. Veámoslo en OllyDbg:

image

En esa dirección vemos el código en ensamblador de la función MessageBoxW, que a su vez llama a la función MessageBoxExW pasándole algún parámetro nulo:

image

Y esto es todo. Como decía en la primera entrada el proceso está resumido aconsejo leer el documento que puse inicialmente para mas detalles. Se puede hacer todo esto de una manera mucho mas sencilla utilizado programas que te facilitan la tarea. Pero mi objetivo es saberlo hacer todo a mano para algún día poder programar algo relacionado con todo esto.

Nos vemos pronto!

viernes, 4 de marzo de 2011

Localizar direcciones en la IAT a mano 1/2

En la anterior entrada una vez localizada la IAT(Import Address Table) nos ayudamos de OllyDbg para saber donde se almacena la dirección de la función MessageBoxW, para después usarla en nuestro código (CALL [Dir de MessageBoxW en la IAT]) y así no tener la dirección “hardcoded”.

image

Vamos hacer esta búsqueda a mano así nos familiarizamos con la estructura de la IT(Import Table) y la IAT. Aviso que el proceso que  sigo está resumido y da cosas por sabidas, recomiendo leer este documento Descabezando archivos ejecutables portables de nuMIT_or antes o durante se lee la entrada.

En el proceso usaré el notepad de la anterior entrada, aquí se puede descargar.

Lo primero es localizar la IT en disco. Para ello hago uso de 010 Editor, en la cabecera opcional dentro de la cabecera PE, está el directorio de datos, una de esos directorios es el directorio de Importaciones:

image

Como vemos podemos encontrar este directorio en la dirección virtual (de ahora en adelante VA) 7604h. Hay que tener en cuenta que está dirección es virtual y nosotros estamos buscando estos datos en el archivo en disco, así que necesitamos traducir de VA a dirección física. Primero necesitamos saber en que sección de todas ira a caer esta VA.

image

La sección text empieza en la VA 1000h y acaba en la 8748h. Así que la IT que está en la VA 7604h pertenece a la sección .text. Esto también nos lo muestra OllyDbg:

image

Ahora para pasar de la VA a la dirección física debemos restar a la VA la VA inicial de la sección text (1000h).
7604h-1000h=6604h
Y a este valor sumarle la dirección física donde comienza la sección, SizeOfRawData:
6604h+400h=6A04h

Vamos a esa dirección con el editor hexadecimal y vemos la IT, la he coloreado en rojo:

image

La IT es un vector de valores DW (Double word, 4 bytes) que sigue esta estructura:
dwRVAFunctionNameList DWORD ;
dwUseless1 DWORD ;
dwUseless2 DWORD ;
dwRVAModuleName DWORD ;
dwRVAFunctionAddressList DWORD ;

He coloreado en verde la primera de las estructuras:

image

Lo que nos interesa ahora es ver el campo dwRVAModuleName que es donde está el nombre de la DLL importada. En esta primera estructura tiene el valor 00007AACh. Este valor a su vez es una VA y debe ser traducida a dirección física. Aplicando el mismo procedimiento que antes tenemos que 7AACh->6EACh

image

Vemos entonces que la primera estructura de la IT se refiere a la DLL comdlg32.dll. Nosotros buscamos la función MessageBoxW que pertenece a la dll user32.dll, así que seguimos con las siguientes estructuras de la IT hasta encontrar justo al final la correspondiente a la DLL User32.dll:

image

Una vez localizada la entrada en la IT correspondiente a User32.dll nos falta recorrer el vector de funciones importadas para localizar MessageBoxW y buscar en el vector de direcciones la dirección de la función.

Eso en la siguiente entrada. (Que no podrá ser hasta el lunes ya que estaré alejado del ordenador).

martes, 1 de marzo de 2011

Añadir código portable a un ejecutable 2/2


Añadir código portable a un ejecutable 1/2

Continuando…

Debemos buscar la función MessageBoxA en la IAT de modo que podamos usar la dirección que haya puesto allí el cargador de Windows. La dirección de memoria donde está la IAT se puede saber mirando en la cabecera PE:

Sin título_thumb[1]

La dirección RVA es 1000h, la dirección en memoria, Virtual Address, será ese valor + ImageBase es decir 0x01001000 justo donde empieza la sección text de código. Podemos abrirlo en OllyDbg y en esa dirección veremos una serie de offsets, al lado nos muestra a la dirección de que función corresponde.

Sin título

Ahora debemos buscar la función MessageBoxA. En msdn podemos ver que es una función que está definida en User32.dll. Así que buscamos esa función y encontramos una parecido MessageBoxW, que es la versión Unicode, nos sirve Guiño.

Sin título

Pero debemos cambiar la cadena que teníamos a una cadena unicode, para que sea compatible con la función.

Sin título

Una vez con todo esto tenemos que adaptar el código ensamblador que pusimos al inicio de la sección para que lea la dirección de la función MessageBoxW desde la IAT, de la dirección 0x010001268.

image

01014017 E8 00000000 CALL 0101401C 0101401C 58 POP EAX 0101401D 6A 00 PUSH 0 0101401F 83E8 1C SUB EAX,1C 01014022 50 PUSH EAX 01014023 50 PUSH EAX 01014024 6A 00 PUSH 0 01014026 A1 68120001 MOV EAX,DWORD PTR DS:[01001268] 0101402B FFD0 CALL EAX 0101402D B8 9D730001 MOV EAX,0100739D 01014032 FFE0 JMP EAX

Y de este modo conseguimos un notepad “infectado”, que muestra un MessageBox al iniciarse y que funcionará correctamente en todos los Windows. Lo subo aquí por si alguien quiere ojearlo.

Pero hemos hecho un poco trampas, porque hemos usado la función MessageBoxW en vez de MessageBoxA, el problema es que notepad no usa MesasgeBoxA así que no Importa dicha función y no podemos obtener su dirección leyendo la IAT. Esto es un problema ya que solo podremos usar las APIs que ya utilice el programa y no todas las de Windows. Se puede solucionar utilizando las funciones GetProcAddress y GetModuleHandle, pero eso ya para otra entrada.

Saludos!

lunes, 28 de febrero de 2011

Añadir código “portable” a un ejecutable 1/2

En anteriores episodios… Añadimos una sección a mano al notepad (lo subo por aquí). Se cambió el EntryPoint para apuntar a la nueva sección. En esa sección incluimos código para mostrar un mensaje usando la dirección hardcoded de MessageBoxA. Y por último se saltaba al EntryPoint Original del programa para que continuase su ejecución normal.

noportable

El problema como comenté es que la dirección de MessageBoxA, en mi caso 76F0FEAE, cambia dependiendo de versiones de Windows, ServicePack instalados, actualizaciones… Así que nuestro nuevo ejecutable “infectado” no sería muy portable.

La solución pasa por entender como Windows hace que un ejecutable se ejecute correctamente en distintas versiones de Windows. Para ello el cargador cuando se quiere ejecutar un programa entre otras cosas localiza la tabla de importaciones que contiene todas aquellas funciones que utiliza el ejecutable y rellena una estructura conocida como Import Address Table, IAT, con las direcciones de esas funciones en la versión actual de Windows.

Para entender todo esto bien, y ya de paso algo sobre como aprovechan esto los virus, recomiendo leerse este PDF Infección de ejecutables de iZan.

Continuará...continuó.

domingo, 27 de febrero de 2011

Añadiendo una sección a un exe

Una de las primeras cosas que se puede hacer con un exe para ir familiarizándonos con el formato PE es añadir una sección nueva, para ello he seguido un tutorial de Ferchu de elhacker.net:

En él primero se expone el formato PE, después se añade una sección y por último se añade código a la sección y se modifica el EP para que se muestre un MessageBox al inicio de la aplicación.

Resulta muy útil usar el editor hexadecimal que comentaba en la otra entrada 010 Editor. Y para añadir código a la sección una vez agregada la sección lo mejor es usar OllyDbg e ir poniendo las instrucciones en ensamblador y verificando que hacen lo que queremos.

Por cierto para localizar la dirección de la función MessgeBoxA lo mejor es abrir Olly, Ctrl+G y escribir MessageBoxA, nos llevara hasta la posición de memoria donde se encuentra dicha función.

Lo malo de esto es que el ejecutable solo funcionara en nuestra versión actual de Windows, en cuanto cambie el idioma, o las actualizaciones la dirección de MessageBoxA habrá cambiado y no funcionara. Por eso en siguientes posts veremos como localizar la dirección de MessageBoxA por código de modo que el exe funcione en todas las versiones de Windows.

sábado, 26 de febrero de 2011

010 Editor, editor hex perfecto para los exe

010 Editor Es un editor hexadecimal que admite el uso de plantillas, es perfecto para ver y modificar los valores del formato PE de un fichero. Por ejemplo:

010 Editor

Una vez descargada esta versión trial.

Es necesario descargarse las plantillas que necesitemos, en este caso las de el formato ejecutable. Hay dos la que mas me ha gustado a mi ha sido la segunda: http://www.sweetscape.com/010editor/templates/files/EXETemplate2.bt

Por comodidad mejor ponerla en el directorio de plantillas: C:\Users\%user%\Documents\SweetScape\010 Templates

Después hay que ir al menú templates > Edit templates list... y añadir la plantilla:

Sin tÃ-tulo

De este modo cada vez que abramos un ejecutable se cargara la plantilla y veremos los campos del PE.

A disfrutar!