martes, 9 de agosto de 2011

Cifrando un ejecutable a mano, dos variaciones

En la anterior entrada hemos cifrado el netcat haciendo xor sobre toda la sección de código. Para ello hemos añadido una sección, en ella se ha escrito el código para descifrar la sección de código y se ha cambiado el EP a esta sección.

Se me ocurren 2 posibles variaciones al método anterior.

La primera es no añadir una nueva sección sino usar los huecos existentes en la sección “.text”. Es muy habitual que debido a la necesidad de que el tamaño de una sección en disco esté alineada con el valor FileAlignment, al final de todas las secciones sobren algunos bytes que solo están ahí para cumplir con el alineado. Podemos usar estos huecos para introducir nuestro código sin la necesidad de añadir una sección de código. Pero claro esto no siempre se puede hacer y lo que se busca a la hora de programar algo es que funcione la mayoría de las veces, así que este método queda descartado.

Aun así para ver que dicen los AV al respecto, he realizado la prueba y lo detectan 19/43, este cambio no confunde a ningún AV.

La segunda variación es la que hace Mati Aharoni en el video que puse en la anterior entrada. Y consiste en no modificar en ningún momento el EP. En cambio donde apunta el EP pone una instrucción de salto, JMP, a la nueva sección donde tenemos el código que descifra y una vez descifrado el código se encarga de ejecutar las instrucciones que había sobrescrito y retornar a la sección “.text” descifrada para continuar la ejecución normalmente.

Originalmente en el EP existen estas instrucciones: image

Tras el cambio quedara así:

image

Fijaos que el resto del código está cifrado con xor, solo se ha conservado el salto.

La sección que hemos añadido y donde salta ese JMP que veíamos quedaría así:

image

Las 2 instrucciones iniciales son las mismas que había en el exe original y que fueron reemplazas por la instrucción JMP.

Subo el exe modificado por aquí. Este es solo detectado por 13/43 antivirus. Que conste que el objetivo no es hacer indetectable el netcat, para eso existen mejores técnicas de las que ya hablé, sino ver diversas formas de cifrar un archivo y ya de paso comprobar cómo afectan a los antivirus.

Esta técnica que acabamos de ver tiene algunas dificultades para ser implantada en un programa. Y es que para insertar el JMP en el EP necesitamos 5 bytes que es lo que ocupa una instrucción JMP, y esos 5 bytes serán sobrescritos afectando a las instrucciones que estuviesen en ese lugar, pero a priori no sabemos cuantas instrucciones son ni que tamaño tienen. Es mas fácil verlo con el ejemplo anterior. Las instrucciones sobrescritas eran:

PUSH 18
PUSH 0040C098

Las cuales ocupan 7 opcodes: 6A 18 68 98 C0 40 00

Sería un grave error hacer el programa que solo copiase solo los 5 opcodes sobrescritos por el JMP. Necesitamos analizar las instrucciones afectadas por esos 5 bytes y conservarlas completamente. Programar esto ya es mas complicado, requiere conocer todas las instrucciones posibles, el tamaño de los operandos, etc… Así que de momento esta variación queda también descartada para realizar un programa automático que cifre un ejecutable, un crypter.

Saludos!

lunes, 8 de agosto de 2011

Cifrando un ejecutable a mano

Buenas!

En las entradas que se han visto hasta ahora sobre los ficheros ejecutables en Windows se explicaba el formato que tiene un exe, cómo añadir una sección, cómo añadir código ejecutable, qué es la IAT y cómo cargar funciones manualmente y alguna otra cosa relacionada. Todo esto tenía un objetivo, ir preparándonos para entender cómo funcionan los protectores de ejecutables e ir programando poco a poco uno.

Y para empezar que mejor que cifrar un ejecutable a mano de la forma mas sencilla posible para después ya desarrollar el programa que haga el proceso automáticamente. La idea es usar la función XOR para cifrar la sección de código de un ejecutable, después insertar al inicio un pequeño código en el mismo ejecutable que deshaga esta operación de cifrado y por último ejecute el código una vez descifrado.

El proceso puede verse en este video de la conferencia ShmooCon 2008 donde Mati Aharoni habla sobre cómo saltarse la detección de los antivirus. Para ello usa la herramienta netcat que es detectada por unos cuantos. Al final del proceso logra que su Antivirus, AVG, no detecte el netcat.

Voy a hacer en esencia lo mismo pero con algunos cambios.

Como Mati, voy a usar el netcat, que se puede descargar de aquí. Nada mas bajarlo, lo he subido a Virustotal y actualmente es detectado por 28/43 antivirus.

Lo siguiente que voy a hacer es añadir una sección al netcat. Para ello uso mi querido 010 Editor. Me ha quedado así:

image

No os olvidéis de cambiar el NumberOfSections, ImageSize y añadir físicamente 1000 bytes al final del fichero. Si tenéis algún problema añadiendo la sección revisad este post de Ferchu sobre cómo añadir una sección a un exe “y no morir en el intento”.

En esta sección que acabamos de crear incluiremos el código que descifre la sección de código del ejecutable y una vez finalizada esta tarea salte a la misma. Para que lo primero que se ejecute en el programa sea este código que ahora veremos es necesario modificar el EntryPoint del ejecutable de netcat para que el programa inicie la ejecución en nuestra sección.

image

En este ejemplo el código que se usará para cifrar la sección será el mismo que se use para descifrarla. Esto es posible porque vamos a usar la función XOR para cifrar los bytes de la sección de código, y esta función tiene una característica curiosa y es que: X XOR C = Y Y XOR C = X

C es la clave que por ejemplo puede ser 0xBB. X es uno de los bytes de la sección de código, una vez cifrado con la clave C obtenemos Y, que será el byte cifrado. Para descifrarlo solo tenemos que volver a aplicar la función XOR con la misma clave.

La sección de código en el ejecutable de netcat es la primera sección, llamada “.text”. Dicha sección se encuentra en este rango de memoria virtual: 401000h-40B000h.

Y con todo esta ahora ya vamos con el código ensamblador que cifrará/descifrará la sección. La idea es situarnos al comienzo de la sección e ir cifrando cada byte de la misma hasta que lleguemos al final. Este código realiza esa tarea:

MOV EAX, 401000  ;Inicio de la sección
XOR [EAX], BB ;Clave usada para la función xor BB
INC EAX
CMP EAX, 40B000 ;Fin de la sección
JNZ 00410005 ;Si no es el fin de la sección seguir en el bucle
JMP 00404AC3 ;EP original

Ahora tenemos el netcat con una nueva sección que contiene el código para cifrar/descifrar. Lo abrimos con OllyDbg y ejecutamos el bucle para que cifre toda la sección “.text”. Para ello lo mejor es poner un breakpoint en el último JMP y darle a ejecutar.

Una vez parado el Olly en el JMP, podemos ver como la sección ”.text” se encuentra cifrada:

image

A la izquierda vemos el netcat original, a la derecha el cifrado. Ahora solo nos queda guardar el ejecutable en este estado, con al sección cifrada. Para ello en OllyDbg selecionamos toda la sección y damos a “Copy to executable > Selection”:

image

Y en la nueva ventana “Save file”.

Ahora ya tendremos todo listo, el netcat con la sección de código cifrada, una nueva sección con el código que la descifrará y el EP apuntando allí. Ahora al ejecutarlo se descifrara la sección y la ejecutará como se haría normalmente.

Subo aquí el netcat tal cual me ha quedado a mi.

Esta versión cifrada la detectan 19/43 antivirus. Antes eran 28. Uno de los que no lo detectan es AVG, el mismo que utilizó Mati Aharoni en su conferencia. Hace años seguramente hubiesen sido mas los AV que no hubiesen detectado este netcat modificado, pero hoy en día muchos antivirus son capaces de mediante emulación o análisis heurísticos detectar que se usa un cifrado XOR y revertirlo para analizar el ejecutable. Otros tantos no detectaban el netcat, ya que en si es una herramienta para “hacking”, pero si detectan esta variante como un programa empaquetado “Malicious Packer”. Hay varias cosas en las que puede fijarse un antivirus para sospechar que es un programa cifrado, tiene 2 secciones con permisos de ejecución, lo cual no suele ser muy normal, la sección donde apunta el EP no es la primera, lo que tampoco es habitual y la sección “.text” no parece contener instrucciones ejecutables.

En siguientes entradas programaré esto en C y se verán los problemas que pueden surgir con este método.

Saludos!


Continuación: Dos posibles variaciones a este método


lunes, 4 de julio de 2011

Formato de ficheros ejecutables, Formato PE

@The_Swash ha redactado un completo documento en el que explica toda la estructura de un fichero ejecutable para Windows.

Es uno de los documentos mas completos en español sobre el tema.

Aquí os dejo el índice:

  1. ESTRUCTURA DE UN FICHERO EJECUTABLE
  2. DIRECCIONES FÍSICAS, VIRTUALES RELATIVAS Y VIRTUALES
  3. IMAGE FILE HADER
  4. IMAGE OPTIONAL HEADER
  5. IMAGE DATA DIRECTORY
  6. IMAGE SECTION HEADER
  7. EXPORT DIRECTORY
  8. IMPORT DIRECTORY
  9. RESOURCE DIRECTORY
  10. RELOCATION DIRECTORY
  11. DEBUG DIRECTORY
  12. TLS DIRECTORY (THREAD LOCAL STORAGE)
  13. DIRECTORIO LOAD CONFIG
  14. DELAY IMPORT DIRECTORY
  15. BOUND IMPORT DIRECTORY
  16. REFERENCIAS
  17. DESPEDIDA

Y el documento, como no.

Saludos!

viernes, 10 de junio de 2011

Me quieren infectar! Pero ¿cómo? y ¿quién?

En la anterior entrada mostré cómo alguien o algo trataba de infectar mi equipo.

¿Cómo?

Está claro que el problema estaba en que el DNS no era el esperado y tampoco el servidor DCHP. Razonando un poco llegué a la conclusión de que había un servidor DHCP falso que era el que me daba los datos para conectarme a internet y uno de esos datos era el servidor DNS malicioso.

Veámoslo en Wireshark. Me desconecto y reconecto a la red Wi-Fi, filtro los paquetes para ver solo el protocolo DHCP “bootp” y me encuentro con lo siguiente:

wireshark_yeah

En los dos primeros paquetes se ve como mi equipo recién conectado a la red inalámbrica solicita (DHCP Request) los datos necesarios para conectarse.

A continuación responden a la solicitud (DHCP ACK) desde 2 direcciones diferentes. 192.168.100.13, la IP de un equipo de mi red y 192.168.100.254, mi router, el único que debería responder. 

El primero en responder es la dirección IP 192.168.100.13, el equipo de mi red, así que es al que hace caso mi portátil. En la captura se puede ver como uno de los datos que nos da en la respuesta a la solicitud es el Domain Name Server (DNS) 188.229.88.8. Como curiosidad esa IP está en Bucarest, Rumania.

Pero no siempre responde antes el equipo “malicioso” que el router. De hecho la mayoría de las veces responde antes el router que el equipo:

wireshark_dhcp_competi

En estas ocasiones mi equipo ignora la segunda respuesta y todo funciona correctamente.

¿Quién?

La pregunta ahora es quién de mis compañeros de piso tiene la IP 192.168.100.13, ¿la belga, los franceses, el indio o serán las polacas? ¿Y será realmente él/ella quien intenta infectarme?

Usando el MAC Address Scanner de Cain se puede ver que equipos están activos en mi rango.

image
Ahí veo que el equipo en cuestión se llama Kwasek-Komputer. El nombre de una de las polacas que vive conmigo. Por supuesto no es ella la que deliberamente intenta infectarme. Es algún tipo de malware, llamémoslo virus que por lo que se ve hace las funciones de un falso servidor DCHP para intentar expandirse por la red de area local, LAN. Tendré que instalarla un antivirus.

La técnica se conoce como Rogue DHCP. Ya en 2009 hablaban de un malware que usaba esta técnica para expandirse por la red local. Seguro que es mas antigua aun.

Buscando en google he encontrado unas cuantas páginas que hablan sobre este virus:
http://malwaresurvival.net/2011/06/01/rogue-dhcp-routes-users-to-malware-attacks/
http://www.dyndnscommunity.com/questions/16870/my-router-provides-the-wrong-dns.html
http://www.bleepingcomputer.com/forums/topic402144.html
http://www.ryumaou.com/hoffman/netgeek/2011/05/dns-redirect-attack/

El siguiente paso sería analizar el ejecutable que se descarga, pero no se yo si lo lograré, suelen estar cifrados, ofuscados, se descargan a la vez otros ejecutables, etc…

Saludos!

Me quieren infectar!

Enciendo el portátil en mi casa, arranca Windows 7, se conecta a la red Wi-Fi, abro el navegador, se abre la página de inicio y ZAS:

fake

www.google.es me dice que para entrar a su página web debo actualizar el navegador. Que extraño…si Google Chrome se actualiza automáticamente, y aun así ¿www.google.es iba a mostrarme ese mensaje tan rádical “o actualizas, o no entras”? Y ese título de la página web tan cantoso: “WARNING!!!”…todo muy raro.

Por curiosidad pulso el botón “Browser update” y se descarga un ejecutable de 58 kbytes llamado “update.exe”, sin icono. Sería mas normal que una actualización se llamase algo como GoogleChrome_Update_11.231.exe y que el ejecutable tuviese el icono de Google Chrome, ¿no?

A estas alturas ya estoy seguro de que hay gato encerrado y que ese ejecutable no es ninguna actualización de Chrome, me la quieren colar…¿Por qué!!?

Pruebo a abrir otras páginas y en todas sale el mismo aviso. Lo intento con Internet Explorer y lo mismo, ¿qué demonios pasa?

Hago ping a www.google.es:

ping

Después hago ping a www.marca.com y la misma IP, todos los dominios me responden con la IP: 188.229.88.8. Abro esa IP en el navegador, http://188.229.88.8/, y veo el mismo mensaje que me salía al principio.

Parece claro que el problema es que mi servidor DNS resuelve todos los dominios con esa IP. ¿Se habrá vuelto loco?

Veamos que servidor DNS estoy usando: ipconfig /all

dnsvafanculo

Mi router tiene la dirección 192.168.100.254 y él mismo hace de servidor DHCP y de servidor DNS, como es normal en los router domésticos. Pero ahí me dice que el servidor DHCP es la 100.13 y el DNS es la misma IP que me salía antes al resolver cualquier dominio :S

Me desconecto de la red Wi-Fi y me vuelvo a conectar (típica solución a todos los problemas informáticos, reconectar, resetear, reiniciar, etc…), vuelvo a mirar la configuración de mi tarjeta de red y sorpresa:

dnsok

Todo está perfecto. Pruebo a conectarme a algunas páginas y todo bien.

Ahora que funciona internet aprovecho a subir la supuesta actualización a VirusTotal para ver que dicen los antivirus al respecto. 23/42 antivirus lo detectan, definitivamente es un malware. Aunque los antivirus no se ponene muy de acuerdo, 4 de ellos lo llaman Gen.Variant.Kazy.

Pruebo a reconectarme varias veces para ver si vuelve a salir el mensaje pero nada. ¿Cómo han aparecido esos valores ahí? ¿Mi equipo está infectado? ¿El router se ha vuelto loco temporalmente?

En la siguiente entrada lo veremos.

Pd: Como curiosidad fijaos que la estética de la página está calcada al aviso de sitios maliciosos de Firefox:

domingo, 29 de mayo de 2011

Obtener la dirección base de kernel32.dll consultando el PEB

En la entrada de Usando GetProcAddress y LoadLibrary para localizar APIs vimos que una de las primeras cosas que hay que hacer es localizar la dirección de memoria donde se carga la dll kernel32.dll. Para ello se utilizaba un código que suponía que en la pila se encontraba una dirección de retorno a una función de dicha dll:

;Obtiene la dirección base de Kernel32
ObtenerKernel32 proc
 mov eax, dword ptr [esp+0Ch];Nos quedamos con la dirección de retorno hacia la funcion createprocess
 and eax, 0FFFFF000h   ;Paginas de 1000h
searchMZ:
 sub eax, 1000h
 cmp word ptr[eax], "ZM"
 jnz searchMZ
 ret

ObtenerKernel32 endp

Esta forma no parece muy correcta, puede que en alguna versión de Windows pasada o futura no funcione bien. Además se supone que se conoce en que posición de la pila estará el valor de retorno que comentaba, esto por ejemplo puede no saberse exactamente si el código se usa para explotar una vulnerabilidad mediante una shellcode que use ese método.

Por suerte existe otra forma de obtener la dirección base de kernel32.dll.

Citando a la wikipedia:

En computación, el Win32 Thread Information Block (TIB) es una estructura de datos en los sistemas Win32 específicamente en la arquitectura x86 que almacena información a cerca del thread que se esta ejecutando.

El TIB esta indocumentado oficialmente para Windows 9x.La serie Windows NT incluye una estructura NT TIB en winnt.h que lo documenta .Wine incluye declaraciones para extender (una parte especifica del subsistema) TIB

El TIB puede ser usado para obtener buena cantidad de información en el proceso sin llamar ninguna API de Win32.Por ejemplo la emulación de GetLastError() , GetVersion(). A través del puntero en el PEB se puede obtener acceso a la tabla de importación (IAT) , los argumentos pasados al proceso etc …

La dirección de esta estructura esta apuntada por el registro FS y en la misma página de wikipedia que he comentado antes pueden verse los campos que tiene. Uno de ellos es el Process Enviroment Block, PEB. Una estructura que contiene información sobre el proceso que ejecuta el hilo:

FS:[0x30] –> Linear address of Process Environment Block (PEB)

En MSDN podemos ver de que se compone la estructura PEB:

typedef struct _PEB {
  BYTE                          Reserved1[2];
  BYTE                          BeingDebugged;
  BYTE                          Reserved2[1];
  PVOID                         Reserved3[2];
  PPEB_LDR_DATA                 Ldr;  //+0x0C
  PRTL_USER_PROCESS_PARAMETERS  ProcessParameters;
  BYTE                          Reserved4[104];
  PVOID                         Reserved5[52];
  PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
  BYTE                          Reserved6[128];
  PVOID                         Reserved7[1];
  ULONG                         SessionId;
} PEB, *PPEB;

Mediante esta estructura podemos saber si un proceso está siendo depurado, los parámetros del proceso y lo que mas nos interesa los módulos que ha cargado el Loader de Windows. En estos módulos se encuentra el propio ejecutable y todas las DLLs que ha cargado Windows para poder ejecutarlo, entre ellas estará kernel32.dll. El campo que nos da esta información es el siguiente:

PPEB_LDR_DATA  Ldr;

Que se encuentra a un desplazamiento de 0x0C desde el principio de la estructura PEB.

La estructura PEB_LDR_DATA a su vez también está documentada en MSDN:

typedef struct _PEB_LDR_DATA {
  BYTE       Reserved1[8];
  PVOID      Reserved2[3];
  LIST_ENTRY InMemoryOrderModuleList; // +0x14
} PEB_LDR_DATA, *PPEB_LDR_DATA;

En MSDN describen esa lista cómo:

InMemoryOrderModuleList The head of a doubly-linked list that contains the loaded modules for the process. Each item in the list is a pointer to an LDR_DATA_TABLE_ENTRY structure. For more information, see Remarks.

Con la siguiente estructura:

typedef struct _LIST_ENTRY {
   struct _LIST_ENTRY *Flink;
   struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;

Y por último la tabla donde apuntan Flink y Blink:

typedef struct _LDR_DATA_TABLE_ENTRY {
  PVOID Reserved1[2];
->LIST_ENTRY InMemoryOrderLinks;
  PVOID Reserved2[2];
  PVOID DllBase; //+0x10 desde –>
  PVOID EntryPoint;
  PVOID Reserved3;
  UNICODE_STRING FullDllName; //+0x1C desde –>
  BYTE Reserved4[8];
  PVOID Reserved5[3];
  union {
    ULONG CheckSum;
    PVOID Reserved6;
  };
  ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

Hay que fijarse que los punteros Flink y Blink de la lista doblemente enlazada no apuntan al comienzo de la estructura LDR_DATA_TABLE_ENTRY sino al campo InMemoryOrderLinks, como he marcado con la flecha –>. Los desplazamientos los he puestos relativos a este punto.

De esta última estructura nos interesan los campos:

PVOID DllBase; 

Que contiene la dirección base donde se ha cargado el módulo y:

UNICODE_STRING FullDllName;

Que es la ruta y nombre del módulo. El tipo UNICODE_STRING está definido también en MSDN:

typedef struct _LSA_UNICODE_STRING {
  USHORT Length;
  USHORT MaximumLength;
  PWSTR  Buffer;
} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING;

Perfecto! Ya tenemos todo lo necesario para lograr nuestro objetivo. La idea es primero acceder al TIB, desde este localizar la estructura PEB, después acceder al valor Ldr a la estructura PPEB_LDR_DATA, utilizar el valor InMemoryOrderModuleList para recorrer la lista mediante el puntero Flink(Follow link) y en cada tabla LDR_DATA_TABLE ver si corresponde al módulo kernel32.dll comparando con el campo FullDllName, si no es así ir a la siguiente tabla, si sí que corresponde con kernel32.dll quedarnos con la dirección base DllBase que es lo que buscamos.

A continuación dejo el código en ensamblador que realiza todas estas tareas. Para hacerlo lo mas genérico he comparado el nombre del módulo con kernel32.dll de forma que no sea sensible a minúsculas o mayúsculas lo que hace un poco mas largo el código:

.386
.model flat, stdcall
option casemap:none
assume fs:nothing

.data
 Kernel32Name db 'K',0,'E',0,'R',0,'N',0,'E',0,'L',0,'3',0,'2',0,'.',0,'D',0,'L',0,'L',0
 Kernel32NameLength dw 24
.code
codigo:
 call ObtenerKernel32PEB
 ret

;Obtiene la dirección de memoria donde se encuentra cargada kernel32.dll y la guarda en eax
ObtenerKernel32PEB proc
 mov eax, [fs:30h]    ;PEB
 mov eax, [eax+0Ch]    ;PEB.Ldr, Loader data
 add eax, 14h     ;PEB.Ldr.InMemoryOrderModuleList.Flink, Puntero al primer modulo
NextTable:
 mov eax, [eax]      ;Nos movemos a la siguiente tabla LDR_DATA_TABLE_ENTRY
 mov ecx, 0
 mov esi, offset [Kernel32Name] ;En esi guardamos la dirección del nombre kernel32.dll en unicode
 mov cx, word ptr [eax+1Ch]  ;LDR_DATA_TABLE_ENTRY.FullDllName.Length, longitud de la cadena unicode
 mov edi, [eax+20h]    ;LDR_DATA_TABLE_ENTRY.FullDllName.Buffer, puntero a la cadena unicode con el nombre del módulo
 ;No nos interesa la ruta entera solo los últimos caracteres, el nombre del fichero
 add di, cx      ;Nos situamos al final de la cadena
 sub di, Kernel32NameLength  ;Y restamos el tamaño de la cadena a comparar
 mov cx, Kernel32NameLength
ComparaCadenas:
 mov bl, byte ptr [edi]
 cmp bl, 'a'      ;Si bl >= 'a' convertir a mayusculas
 jb Mayuscula
 sub bl, 20h      ;Pasa de minusculas a mayusculas
Mayuscula:
 cmp bl, byte ptr[esi]
 jnz NextTable     ;Si no es kernel32.dll mirar en la siguiente tabla
 inc edi
 inc esi
 dec cx
 jnz ComparaCadenas
 ;Si llega aquí es que la cadena era kernel32.dll, cogemos el dato que nos interesa del modulo
 mov eax, [eax+10h]    ;eax = LDR_DATA_TABLE_ENTRY.DllBase
 ret
 
ObtenerKernel32PEB endp

end codigo

Es bastante lioso manejar tantas estructuras y entender el código en ensamblador, lo mejor para entenderlo es seguirlo poco a poco con un depurador, ver las estructuras en memoria y muuucha paciencia.

Y así obtendríamos la dirección de memoria donde está cargada la librería kernel32.dll, ahora ya podríamos seguir con el proceso que realizábamos en la otra entrada de buscar las funciones GetProcAddress y LoadLibrary.

Aquí dejo una entrada de LordRNA donde hace lo mismo de forma muy similar Gracias a @The_Swash también por su solución al mismo problema.

Un saludo!

domingo, 22 de mayo de 2011

Cargando funciones importadas manualmente

@The_Swash no para quieto. Acaba de terminar este documento donde explica como rellenar la IAT desde código ensamblador. Muy útil para hacer que un protector de ejecutables que cifre la Import Table y después en ejecución se descifre y rellene la IAT para que el programa funcione correctamente. Dejo a continuación la introducción que ha escrito @The_Swash:
Hola, aquí estoy escribiendo otro artículo que he estado preparando desde el día en el que publiqué el anterior o por lo menos la base.
En este artículo intentaré mostrarles como cargar las funciones que importamos manualmente, es decir no participará ni dependeremos del sistema operativo.
¿Con que fin cargamos las funciones manualmente?
Bueno, en realidad tengo 2 objetivos y son:
  1. Mostrar como Windows carga las direcciones de las funciones (API) que importamos.
  2. Una vez conociendo como funciona, podremos relacionarlo con Empaquetadores y
    cifradores de archivos.
Como todo necesitaremos conocer un poco de lo que trataremos claro teniendo algunas nociones sobre el formato portable executable (PE) y posteriormente dejaré un código que se
encarga de hacer esta tarea, en realidad la base de todo esto es el código porque a mano sería
muy complejo.
Muchas gracias por estos documentos!

domingo, 15 de mayo de 2011

Ejemplo de uso de TLS Callbacks Funtions

@The_Swash me ha enviado este documento que ha redactado él explicado el uso de Thread Local Storage Callbacks Functions para ejecutar código antes de la propia ejecución del programa en el Entry Point.

Con esto se puede conseguir que por ejemplo cuando se abra un exe con OllyDbg antes de que pare en el EP se ejecute código que detecte que el ejecutable esta siendo depurado y modifique parte del código del ejecutable para engañar a quien intente realizarle ingeniería inversa. Esto es usado desde hace tiempo en el malware, protectores de ejecutables, packers, etc…

Es posible configurar OllyDbg para que se detenga antes del EntryPoint y evitar que se ejecute este código. Para ello hay que ir a Options>Debugging Options>Make first pause at y seleccionar System breakPoint.

Gracias por el documento @The_Swash!

sábado, 7 de mayo de 2011

Usando GetProcAddress y LoadLibrary para localizar APIs 2/2

En la anterior entrada vimos la necesidad de utilizar las funciones GetModuleHandle y GetProcAddress para invocar a otras funciones de Windows.

No hay que olvidar que el objetivo de todo esto es poder añadir código a un ejecutable ya compilado el que seguramente no use las funciones que nosotros necesitamos.

Lo primero a tener en cuenta es que la función GetModuleHandle en realidad devuelve la dirección de memoria donde está cargada una DLL. La dirección donde se carga Kernel32.dll no siempre es la misma así que necesitamos buscar donde ha cargado Windows la librería.

Una de las formas de hacer esto la encontré en los manuales de programación de Virus de ZeroPad que podéis encontrar en el grupo de google de SectorVirus.

;Obtiene la dirección base de Kernel32
ObtenerKernel32 proc
 mov eax, dword ptr [esp+0Ch];Nos quedamos con la dirección de retorno hacia la funcion createprocess
 and eax, 0FFFFF000h   ;Paginas de 1000h
searchMZ: 
 sub eax, 1000h
 cmp word ptr[eax], "ZM"
 jnz searchMZ
 ret
 
ObtenerKernel32 endp

El código lo que hace es tener en cuenta que el loader de Windows cuando carga un ejecutable con la función CreateProcess se deja en la cima de la pila el valor de retorno a la función CreateProcess. Y como esta función está en Kernel32.dll ya tenemos una dirección de memoria de kernel32, a continuación va restando de 1000h en 1000h hasta encontrar el inicio de la DLL, los caracteres “MZ”. Este método lo he probado en Windows XP e Windows 7. Desconozco si en versiones viejas funciona o no.

Otra opción para encontrar la dirección donde se ha cargado Kernel32.dll es recorrer ciertas estructuras del PEB, pero la cosa ya se complica. En otra entrada se vera un método mas genérico.

Una vez hallado el inicio de kernel32 lo siguiente es localizar la tabla de funciones exportadas, ExportTable, accediendo a la tabla de directorios, PE+78h. Sabiendo donde está la ExportTable, se accede al campo ExportNameTable, ET+20h, donde están los nombres de todas las funciones exportadas y vamos comparando los nombres con la función que buscamos. Una vez localizado recordamos la posición donde lo hemos encontrado y mediante la tabla Export Ordinal Table obtenemos el índice para ya por fin acceder a la tabla Export Address Table que contiene la dirección de la función que tanto a costado conseguir jeje.

Lo he explicado muy resumidamente, en el capítulo 7 de SectorVirus que cuelgo aquí está explicado con todo detalle la estructura de la ExportTable y como recorrerla para encontrar una determinada función.

A continuación dejo la función en ensamblador que hace esto. Necesita saber la dirección de kernel32 hallada anteriormente.

.data
Kernel32Dir dd 0
PEHeader  dd 0
ET    dd 0
PosicionEAT dw 0
Contador dd -1
FuncionBuscada db "GetProcAddress",0
FuncionBuscadaLen dd 0Eh

.code
ObtenerGPA proc
 mov eax, [Kernel32Dir]
 add eax, [eax+3Ch]    ;Obtenermos el inicio del PE
 mov [PEHeader], eax
 add eax, 78h     ;RVA de la export table
 mov eax, [eax]
 add eax, [Kernel32Dir] ;Pasamos de dirección relativa virtual, RVA, a dirección virtual
 mov [ET], eax    ;Guardamos el valor
 add eax, 20h    ;Nos situamos en la ExportNameTable, ET+20h
 mov eax, [eax]
 add eax, [Kernel32Dir]  ;RVA->VA
bucle:       ;Bucle para comprobar si es la función GetProcAddress
 inc [Contador]    ;Para saber en que posicion está la funcion
 mov ebx, [eax]    ;Direcion del nombre de la funcion buscada
 add ebx, [Kernel32Dir]  ;RVA->VA
 mov esi, ebx
 add eax, 4      ;Siguiente nombre
 lea edi, [FuncionBuscada]
 mov ecx, [FuncionBuscadaLen]
 repe cmpsb      ;Compara esi y edi, con una longitud de ecx
 jnz bucle
 ;Se mira en la tabla de ordinales para saber en que posición esta la funcion en la tabla de funciones
 mov ecx, [ET]
 mov ecx, [ecx+24h]    ;EOT
 add ecx, [Kernel32Dir]
 mov eax, [Contador]
 add eax, eax     ;eax=eax*2
 add ecx, eax
 mov ax, word ptr [ecx]
 mov [PosicionEAT], ax
 ;Por ultimo se accede a la posicion de la EAT para hallar la direccion de la funcion
 mov eax, [ET]
 mov eax, [eax+1Ch]
 add eax, [Kernel32Dir]
 mov ebx, [Contador]
 rol ebx, 2      ;Contador*4
 add eax, ebx
 mov eax, [eax]
 add eax, [Kernel32Dir]  ;Retornamos en eax la dirección de la función
 ret

ObtenerGPA endp
El código está mucho mejor documentado en el capítulo de SectorVirus que he mencionado antes. Con esto ya podríamos llamar a GetProcAddress y obtener las direcciones de las funciones que nos hagan falta. Un saludo!

domingo, 1 de mayo de 2011

Usando GetProcAddress y LoadLibrary para localizar APIs 1/2

En las dos entradas que escribí sobre añadir código portable a un ejecutable:
http://el-blog-de-thor.blogspot.com/2011/02/anadir-codigo-portable-un-ejecutable-12.html
http://el-blog-de-thor.blogspot.com/2011/03/anadir-codigo-portable-un-ejecutable-22.html

Hice trampas o mas bien me facilite mucho la situación. Ya que me servía de que la API que iba a usar el código ya la importaba el ejecutable (MessageBoxW). Pero no siempre podemos confiar en tener esa suerte.

Así que lo suyo es primero encontrar la dirección de la API que necesitamos y después usarla. Para tal tarea se utiliza la API GetProcAddress, que pasándole el handle de una dll (la dirección de memoria donde empieza la dll) y el nombre de la función buscada nos devuelve la dirección de la misma. Para obtener el handle de una DLL que ya tiene cargada el ejecutable se usa la funcion GetModuleHandle. Hay que tener en cuenta que el cargador de Windows cuando arranca un programa siempre carga las dlls Kernel32.dll y NtDll.dll aunque el programa no necesite ninguna API de las mismas.

Esto se puede ver compilando un simple programa en ensamblador que solo tiene una instrucción nop y abriendolo con OllyDbg:

.386
.model flat, stdcall
option casemap:none

.code
codigo:
nop
end codigo

image

Así que si la API que necesitamos está en las DLLs Kernel32.dll o NtDll.dll nos vale con usar la función GetModuleHandle y pasarle ese valor a GetProcAddress junto al nombre de la API buscada:

HMODULE h = GetModuleHandle("kernel32.dll");
GetProcAddress(h, "ExitProcess");

Si no deberemos usar la API LoadLibrary para cargar una DLL en la memoria del proceso. Por ejemplo para los anteriores entradas necesitábamos usar la API MessageBoxA. Mirando en MSDN sabemos que se encuentra en la DLL User32.dll.

HMODULE h = LoadLibrary("User32.dll");
GetProcAddress(h, "MessageBoxA");

La función LoadLibrary a su vez la podemos localizar mediante el uso de GetProcAddress:

HMODULE h = GetModuleHandle("kernel32.dll");
LoadLibraryF = (void*)GetProcAddress(h, "LoadLibrary");
h = LoadLibraryF("User32.dll");
GetProcAddress(h, "MessageBoxA");

Vemos que las 2 funciones imprescindibles para cargar el resto son GetModuleHandle y GetProcAddress.

Pero fijaos en un problema, si un programa no importa las funciones GetModuleHandle y GetProcAddress no sabemos en que dirección están y por lo tanto no podemos encontrar otras APIs. Nos encontramos en un bucle, para saber la dirección de GetProcAddress necesitamos utilizar GetProcAddress y es lo que no sabemos.

En la siguiente entrada veremos como se soluciona esto.