Título: Introducción basica al maldev Publicado por: D3s0rd3n en 19 Diciembre 2023, 16:28 pm Casi no se ven mucho acerca del desarrollo de malware asi que quiero aportsr compartiendo algunas cositas que voy encontrando. Aqui pienso escribir los conceptos basicos del desarrollo de malware usando el WinAPI. Como por ejemplo el cargado dinamico de funciones, accesando El PEB (Process Environment Block [Bloque de entorno de Processos]) y la ejecucion de funciones en el codigo. Además de la obufscacion y encodificacion de la payload usando cosas como XOR o AES para hacerla más difícil de de detectar. Entre otras :3.
Cargado y Ejecucion Dinámica de una Función[size] De ejemplo vamos a empezar con algo simple. La función MessageBoxA que simplemente abre una ventanilla para mostrar un mensaje. Esta función es parte de WinAPI. Nuestro código va a ser simple pero veremos cómo montar funciones dinamicamente. Esto es uno de los principios fundamentales para evadir detección. Código
En Este código estamos llamando la función directamente. Lo que significa que será enlazada estáticamente al momento de la compilación. Esto en resumen significa que su código será incluido en nuestro programa y no se tendrá que cargar al momento de la ejecución. Ahora esto es muy fácilmente detectado al momento de análisis así que lo llevaremos otro paso. Observemos el siguiente código: Código
El Codigo hace lo mismo que el anterior la diferencia es que aquí estamos cargando la función dinamicamente mediante GetProcAddress. Esta función (que literalmente se llama "obtén dirección de proceso") en el momento de ejecución irá a USER32.dll y buscará la dirección de MessageBoxA. Para hacer que esto funcione, necesitamos un puntero de función que get_MessageBoxA que coincida con la función MessageBoxA. Usamos está dirección para asignarla al puntero y a travez del puntero accesamos la función. El usar punteros nos ayuda a obfuscar la funciones que usamos y hacerle más difícil al análisis estático que es lo que estamos haciendo. Considera el siguiente código que son dos funciones que habren ventanillas con un mensaje. Estas funciones serán importadas de un dll: Código
Esto parece normal, tenemos dos funciones que son importadas de un dll y cada una abre una ventanilla como lo dije. Pero la cosa aquí es que dentro de DllMain podemos cambiar el comportamiento de func1. Esto para dar una impresión inicial de código benigno y después correr el código sospechoso. La cosa es que esto solo ocurrirá al momento de ejecución haciéndolo muy bueno para evitar detección. Título: Re: Introducción basica al maldev Publicado por: D3s0rd3n en 19 Diciembre 2023, 16:28 pm PEB
Cuando en Windows se abre un ejecutable, por ejemplo chrome.exe, este llamará la función CreateProcess del API de win32 lo que le solicita al sistema operativo que cree un proceso y comience la ejecución. A nivel kernel se creará una estructura de datos EPROCESSES. Luego windows aparta memoria virtual e incluye la representación de memoria física en EPROCESS. Entonces el PEB (Process Environment Block [bloque de entorno de proceso]) es una estructura de datos donde Windows guarda información y configuración asociada con un proceso. El PCB (Process Control Block [bloque de control de proceso]) contiene información que le interesa al kernel como el CPU preferido de este proceso. El TCB (Thread Control Block [Bloque de Control de Hilos]) es lo que usa el kernel para determinar que hilo usar y su jerarquía de preferencia, que es lo que hace el kernel a un nivel muy bajo (pero esa es otra historia). El PEB se accesa para obtener información del proceso y la información asociada a el como las direcciones base de las librerías dinamicas. Miremos el siguiente código: Código
Como se puede ver PEB son estructuras robustas. Y las estructuras como _PEB_LDR_DATA32 son versiones simplificadas del PEB como tal. Estas contienen información y las direcciones de los modulos que estan cargados en memoria. Código
Para acceder la dirección base de un modulo que este cargado en memoria se usa la funcion GetModHandle. Dentro de el PEB hay una estructura llamada PEB_LDR_DATA que contiene la información de un modulo cargado en la memoria. Tambien hay una lista enlazada a los modulos de la memoria que se llamada InMemoryModuleOrderList. La funcion GetModHandle antes mencionada cicla por los elementos de esta losta hasta encontrar el modulo especificado por el parámetro libName. El PEB se puede encontrar en fs (0x30) en el TEB (Thread Environment Block [Bloque de Hilo de Entorno]) para procesadores x86 y en gs (0x60) para procesadores x64. Despues usaremos la fincion GetFuncDir para obtener la dirección de una funcion de gro de un modulo. Código
Esta funcion toma el parámetro baseModulo que es la dirección base del módulo. Despues se fija en la tabla de exportación (tablaExp) para buscar la funcion que tenga de nombre szFuncName. La tabla de exportación es parte de la estructura de datos del modulo lo cual es procesado por el PEB. La tabla de exportación es parte del archivo PE y nos da una manera de acceder las funciones de este externamente:
Ahora, dentro de un ciclo vamos a comparar el nombre de la funcion exportada sz_CurrApiName con el nombre de la funcion szFuncName. Cuando coincide arrojamos fatos sobre la función. Código
Si el nombre de la funcion coincide con el nombre de la funcion deseada arrojamos su dirección. Calculamos la dirección de la funcion haciendo referencia a arrFuncs y al ordinal. Esto es importante por que sto nos permite realizar una inyección de proceso y cargar una funcion dinamicamente. Ahora tenemos la función main: Código
Aqui usamos la función GetModHandle para encontrar la dirección de kernel32.dll dentro del proceso actual. Usamos el PEB para revisar la lista de modulos cargados por uno que coincida con el nombre kernel32.dll. Teniendo esta, usamos GetFuncDir para encontrar la dirección de WinExec que esta despues de la de kernel32.dll y es por eso que tomamos su dirección como la dirección base. Despues invocamos la funcion WinExec dinamicamente usando la dirección obtenida. Transformamos ptr_WinExac a el tipo adecuado para que sea un puntero de esta funcion. Y luego la invocamos con el argumento "calc" para abrir la calculadora. Esto muestra como podemos ubicar dinamicamente la funcion WinExec dentro de kernel32.dll y ejecutarla para abrir la calculadora (que obviamente en un escenario de maldev sería otra cosa). Esto es una manera de manipular codigo usando el PEB, localizando y utilizando funciones de los modulos cargados. Ahora prestemos atención a una linea interesante: Código: ((UINT(WINAPI*)(LPCSTR, UINT))ptr_WinExec)("calc", SW_SHOW); Esta es donde se invoca dinamicamente la funcion WinExec. Ahora miremosla mas a fondo.
Lo que sucede es que el codigo inyecta dinamicamente la ejecución que nosotros deseamos a un proceso legitimo. En vez de tener que incluir la funcion WinExec estáticamente, cad que corre la localiza y la ejecuta dinamicamente. Esto se usa comúnmente en el malware para no tener que importar ciertas funciones de interés y asi se menos detectables.[/list] Título: Re: Introducción basica al maldev Publicado por: fary en 21 Diciembre 2023, 05:48 am Me gusta el tema, seguiré tu post.
Gracias por el aporte. Título: Re: Introducción basica al maldev Publicado por: D3s0rd3n en 21 Diciembre 2023, 21:50 pm Me gusta el tema, seguiré tu post. Gracias por el aporte. Gracias, hago muchas cosas a la vez pero intentaré compartir lo mas que pueda. Título: Re: Introducción basica al maldev Publicado por: D3s0rd3n en 21 Diciembre 2023, 21:51 pm Enganchado IAT
El cargado dinamico de funciones es una tecnica que se usa en el ámbito del desarrollo de software para windows y a menudo se usa en el maldev. Una manera de lograr esto es usando IAT hooking (enganchado de Import Address Table [tabla de direcciones de importación]). La IAT contiene las direcciones de las funciones que importa un programa de algun módulo. Esta tecnica que veremos nos ayuda a interceptar y modificar invocación de funcion dentro de la ejecución de un programa. (https://pomf2.lain.la/f/5611urs5.jpg) Esta imagen nos muestra la estructura de una IAT y como interactuaria un enganche con ella. Primero el programa en cuestión llama la función MessageBoxA de el WinAPI. El programa busca la dirección de esta función y luego brinca la ejecución a ella. Aqui es donde esta el código legitimo de MessageBoxA. Asi funciona la IAT en el contexto de abrir MessageBoxA: Código
Esta invocación de la función generalmente se hace mediante una función o una librería del API de Windows. Cuando un programa invoca una función, lo haces de esta manera y no accesando el código de la función como tal. Asi busca su dirección en la IAT que contiene las direcciones de todas kas funciones importadas. Una vez encontrada esta dirección la ejecución se va a ella. Yo me lo imagino algo asi como un DNS para funciones. Rn este caso se obtiene una dirección legitima de MessageBoxA. Código
Entonces aquí sucede algo diferente. En vez de ejecutar la función MessageBoxA, la entrada en la IAT es modificada para que apunte a otra función. Asi que cuando se ejecuta MessageBoxA en el programa, en realidad se esta ejecutando la función que ka reemplaza. Esto nos permite alterar el funcionamiento esperado del programa. Título: Re: Introducción basica al maldev Publicado por: D3s0rd3n en 22 Diciembre 2023, 04:44 am Process Hollowing[/b]
Le digo ahuecamiento de proceso por que no sé cómo traducir "hollowing" en este contexto xd. Pero espero que con la explicación sea mas claro. Esta tecnica comienza con la creacion de un proceso legitimo en estado de suspensión. Este estado nos permite inyectarle codigo para que se ejecute dentro de el. Para que se dé de una manera exitosa, se requiere que la fuente del proceso cumpla con algunos requisitos:
Ahora un ejemplo de la creación de un proceso en estado suspendido. Cuando se carga, el codigo y datos se reemplazan con el código y datos de otro ejecutable. Lo que crea un proceso suspendido sobre el cual de pueden hacer operaciones con su memoria para cargar una nueva imagen. Código
La funcion CreateProcessA sirve para crear una nueva instancia de el proceso actual o de algun ejecutable en modo suspendido. Esto se hace con el parámetro CREATE_SUSOENDED lo que significa que su ejecución sera pausada. Despues de su creación se usa VirtualAlloc para alocar memoria para su contexto. La estructura CTX guarda información sobre el estado del proceso. Obtener y actualizar el contexto La funcion GetThreadContext obtiene informacion del contexto del hilo principal del proceso suspendido (PI.hThread). Este contexto es el que esta guardado en CTX. El contexto ahora se actualiza en preparación para la ejecución de codigo nuevo. Hablando mas técnicamente el registro EAX se establece para apuntar al codigo nuevo. Despues se copia el encabezado del PE dentro de la memoria a traves de WritePricessMemory. Esto para asegurar que se haya cargado correctamente. Ahora, un ciclo pasa por las secciones de la imagen (adentro del SectionHeader osea el encabezado de la sección.). Esto copia los datos de la imagen a el espacio designado para el proceso usando WriteProcessMemory. A este punto el proceso del ahuecado del proceso esta acomodado. Los datos y codigo del otro PE han sido cargados a la memoria. La ejecución continuara resultando en que el codigo nuevo se ejecute en el contexto del programa inicial. Código
La dirección de destino se calcula como CTX->Ebx + 8 y se escriben 4 bytes. Esta operacion establece el punto donde comienza la ejecución del nuevo código. El registro CTX->Eax es actualizado con el nuevo punto de entrada del codigo nuevo. En resumen lo que hace es establecer EIR (el registro de instruccion) a el punto donde esta el codigo que queremos cargar. El punto de entrada se obtiene del encabezado de la imagen. Y ahora que estamos listos invocamos ResumeThread para continuar la ejecución del proceso suspendido. Es aqui donde el proceso empieza a ejecutar el codigo cargado empezando por el punto de entrada. El codigo que se inyectó en el proceso suspendido ahora tiene el control de la ejecucion del proceso. Código
Cuando este código es ejecutado, se obtiene el directorio del ejecutable como en si. Hay una revisión conditional para checkar CurrentFilePath usando strstr. Si este directorio contiene "chrome.exe" muestra el mensaje "holi" usando MessageBoxA. O la ejecucion continua si el directorio no cumple con la condicion. Se ejecuta RunPortableExecutable. Nuestro objectivo de ahuecado seria "chrome.exe", le pasa el codigo al proceso hueco y si no busca otra imagen. |