Archivo de la etiqueta: Buffer overflow

Usando Sulley para fuzzear aplicaciones locales

Como comenté en el anterior post, Sulley es una herramienta impresionante para fuzzear aplicaciones, pero viene más preparada para atacar servidores y no para aplicaciones locales. Como la generación de mutaciones funciona muy bien, he creado un script que usa esta funcionalidad, para atacar aplicaciones locales que cargan ficheros por línea de parámetros, es decir, ficheros de tipo DOC, XLS, PDF, TXT, SWF, etc. Esto unido a pydbg de PaiMei para controlar las excepciones.

La verdad es que el script no tiene ningún misterio. Lo que hace básicamente es:

  1. Genera una mutación con Sulley
  2. Crea un fichero con el resultado
  3. Abre el programa a fuzzear pasando como parámetro el fichero generado
  4. Pausa de 5 segundos para dejar que abra correctamente y, para que el manejador de excepciones haga su trabajo en caso de haber un crasheo
  5. Si todo ha funcionado bien, cierra y lanza la siguiente mutación
  6. En caso de crasheo, muestra los datos por pantalla y termina

El fichero de sesiones variará poco de una aplicación a otra, teniendo que indicar únicamente la ruta del EXE y la extensión que se desea usar para el fichero. La librería se la tendrá que crear cada uno, en función a lo que se desee fuzzear (PDF, SFW, etc).

He creado un ejemplo sencillo para fuzzear BACnet OPC Client 1.0.24. Podeis ver la vulnerabilidad y descargar el programa aquí: http://www.exploit-db.com/exploits/15026/. Hace tiempo escribí un tutotrial sobre como explotar esta aplicación (para iniciados en el fantástico mundo de los Buffer Overflows en Windows) en el que lo hacíamos de forma manual todo. Lo podeis leer aquí: http://pepelux.org/download.php?f=papers/BACnet.pdf

Repito que con ese programa no tiene mucho sentido usar un fuzzer ya que se explota con una cadena demasiado larga. Pero sí que tendría sentido para usarlo en un navegador o en un lector de PDFs, ya que es donde Sulley nos permite usar su potencial y, con unas buenas librerías, se pueden hacer maravillas.

Aquí va el código de la sesión:

# script to fuzz SCADA BACnet
#
# by:
# Pepelux <pepeluxx@gmail.com> - http://www.pepelux.org/ && http://www.enye-sec.org/

from sulley import *
from requests import bacnet_generic    # library to fuzz
from time import sleep
from pydbg import *
from pydbg.defines import *
import os
import threading
import sys

req=s_get("bn")        # session
stop=0

tmpfolder="c:\\sulley\\tmp\\"
name=tmpfolder+"test.csv"
proc_path="C:\\Program Files\\SCADA Engine\\BACnet OPC Client\\";
proc_name="BACnOPCClient.exe";

################################
### ACCESS VIOLATION HANDLE ####
################################

def av_handler(dbg):
 print "Access Violation Handler"

 print dbg.dump_context()

 try:
 mod = dbg.addr_to_dll(dbg.context.Eip)
 print 'Eip module path : ', mod.path
 print 'Eip module base : 0x%08x'%mod.base
 print 'Eip offset : 0x%08x '%(dbg.context.Eip - mod.base)
 except:
 print 'Unable resolve Eip module'

 global stop
 stop=1

 dbg.stack_unwind()

 for i in dbg.disasm_around(dbg.context.Eip, 12):
 print "%x %s"%i

 dbg.terminate_process()

 return DBG_CONTINUE

##################################
### START PROCESS USING PYDBG ####
##################################

class start_proc (threading.Thread):
 def __init__(self, t_proc_name, t_name):
 threading.Thread.__init__(self)
 self.t_proc_name = t_proc_name
 self.t_name = t_name

 def run(self):
 dbg = pydbg()
 dbg.load(self.t_proc_name, self.t_name)
 dbg.set_callback(EXCEPTION_ACCESS_VIOLATION, av_handler)
 dbg.run()

#####################
### STOP PROCESS ####
#####################

class stop_proc (threading.Thread):
 def __init__(self, t_proc_name):
 threading.Thread.__init__(self)
 self.t_proc_name = t_proc_name

 def run(self):
 os.system("taskkill /T /F /IM "+self.t_proc_name+">"+tmpfolder+"/null")

#############
### INIT ####
#############

if not os.path.isdir(tmpfolder):
 os.mkdir(tmpfolder)

for i in range(req.names["ini"].num_mutations()):
 file = open(name,"w")
 file.writelines(s_render())
 file.close()

 print "starting target process (session "+str(i)+")"
 t = start_proc(proc_path+proc_name, name)
 t.start()

 sleep(5)
 print "stopping target process"

 t = stop_proc(proc_name)
 t.start()
 t.join()

 if (stop == 0):
 s_mutate()
 else:
 sleep(2)
 sys.exit()

Y la mini-librería usada en este caso:

# script to fuzz SCADA BACnet
#
# by:
# Pepelux <pepeluxx@gmail.com> - http://www.pepelux.org/ && http://www.enye-sec.org/

from sulley import *

########################################################################################################################

s_initialize("bn")
if s_block_start("ini"):
 s_static("OPC_TAG_NAME,OBJECT_TYPE,INSTANCE,OBJECT_NAME\n\\")
 s_string("A", size=400, padding="A")
 s_static("\\<OPC Server Name>\\<OPC Tag Name>,0,0,\n")
s_block_end()

Si a alguien se le ocurre alguna forma de mejorar esto que me mande un mail 🙂

Un saludo a Roi y a Boken, que me han ayudado con muchas dudas