Bueno, esto lo hable con mek, pero como curra demasiado, pues no pudimos seguir avanzando juntos.
Me he documentado todo lo que he podido (tanto como se crean las excepciones controladas por el usuario, asi como que pasa cuando el sistema toma el control de la excepcion).
De todas formas, antes de empezar, algunos documentos interesantes:
http://www.thc.org/papers/Practical-SEH-exploitation.pdfhttp://members.v3space.com/blackfenix/seh.htmlhttp://www.shellcode.com.ar/docz/bof/UN-shellcodes_1.txtY algunos de Micro$soft, solo tienen que buscarlos
POR FAVOR, TANTO SI HAY ERRORES PEQUEÑOS, COMO GRANDES, COMO INMENSAS METEDURAS DE PATA, DECIDMELO!!!! AGRADEZCO TODA LA INFORMACION REFERENTE AL TEMA!!!! (pero de buen rollo joder)
Bueno, el caso, todos conocemos (mas o menos) el tipico overflow de pila:
#include <stdio.h>
#include <string.h>
int main (int argc, char **argv) {
char buffer[7];
strcpy (buffer, argv[1]);
return 0;
}
Si le metemos por argumento AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA petara el programa, con EIP=41414141 (A en Hexadecimal es 0x41)
Pero porque se produce el overflow exactamente? Echemos mano del olly...
CALL <JMP.&msvcrt.strcpy> ; \strcpy
ADD ESP,10
MOV EAX,0
LEAVE
RETN
El overflow se produce en el strcpy, ya que al copiar en la pila mas AAAs de la que soporta el "buffer", sobreescribe la direccion de retorno de MAIN, que es llamada en la instruccion RETN.
Si ponemos un BP en RETN, vemos esto en la pila:
0022FF74 41414141
0022FF78 41414141
0022FF7C 41414141
ESP apunta a 0022FF74, que es donde deberia estar la direccion de retorno de main (en este caso un return 0, y empezar la finalizacion del programa). Pero esta 41414141 (AAAA), que es donde se dirigira EIP. Esta es la clasica direccion de "ret" o "ret address", etc, donde tenemos que conseguir que EIP coja un valor que nos interese, y que acabe en nuestra shellcode. Pero eso esta mas que explicado por todos laos

Bueno, EIP coge el valor de 41414141, y al tratarlo de ejecutar, produce la excepcion:
Access violation when executing [41414141] - use Shift+F7/F8/F9) to pass exception to program
Aqui mas o menos ya sabemos que hacer, el clasico overflow de pila (lo que pasa en el exploit del Winamp). Yo cambie 41414141 por un offset de olepre32.dll que llamaba a un jmp esp, y como ESP apuntaba a mi shellcode, pues se ejecutaba y listo. Un stack overflow facilisimo

Peeero, no siempre es tan facil

Ojo, a partir de aqui, soy novato total xDDDDDD, no respondo de gazapos, y si escribo esto, es para ayudar y que me ayuden.
Bueno, si os fijais en la pila, despues de meter las AAAAs en ella, antes de que pete el programa:
0022FF78 41414141
0022FF7C 41414141
0022FF80 41414141
0022FF84 41414141
0022FF88 41414141
0022FF8C EE004141
0022FF90 E2CEBC00
0022FF94 003D29B8
0022FF98 00000000
0022FF9C 7FFDF000
0022FFA0 /0022FFC0
0022FFA4 |00401013 RETURN to pruebaSE.<ModuleEntryPoint>+13 from pruebaSE.00401080
0022FFA8 |00000001
0022FFAC |EE1A0045
0022FFB0 |77F4C294 RETURN to ntdll.77F4C294
0022FFB4 |77E61417 RETURN to kernel32.77E61417 from ntdll.ZwSetInformationThread
0022FFB8 |FFFFFFFE
0022FFBC |00000009
0022FFC0 \0022FFF0
0022FFC4 77E6141A RETURN to kernel32.77E6141A
0022FFC8 004D7EF9
0022FFCC 0012D548
0022FFD0 7FFDF000
0022FFD4 F4B47CF0
0022FFD8 0022FFC8
0022FFDC 8053A675
0022FFE0 FFFFFFFF End of SEH chain
0022FFE4 77E7B2E5 SE handler
Fijaros al final hay un SE handler, un manejador de excepciones. Esto nos va a servir para jugar

Un SE handler es un manejador de excepciones. Por ejemplo, cuando EIP alcaza la direccion 41414141 y ve que no puede ejecutar, se produce una excepcion. Hay muchos tipos de excepciones, las mas comunes son divison por 0, lectura/escritura en memoria invalidas, etc....
En tu programa, puedes incluir manejadores que permitan "arreglar" excepciones, y seguir ejecutandolo con total normalidad. Esto es otro tema que no viene al caso (como hacerlo), hay bastante info por la red, aparte que no lo entiendo muy bien

Bueno, si la excepcion no la puede manejar el SEH de ese thread, la "chainea" a otro SEH que la trate, si este no puede, a otro, etc.... Eso lo podemos ver en la pila:
XXXXXX00 XXXXXX1F Point to next SEH Handler
XXXXXX04 00445500 SE Handler
............
............
XXXXXX1B XXXXXX2F Point to next SEH Handler
XXXXXX1F 00446000 SE Handler
............
.............
XXXXXX2B FFFFFFFF End of SE Chain
XXXXXX2F 77E7B2E5 SE Handler
Los Handlers van chaineados (encadenados) y se van ejecutando uno tras otro, hasta que uno devuelva en EAX 0 (significa que ha tratado la excepcion, con lo que puede volver a tratar de ejecutar el codigo que produjo la excepcion)
Si ninguno de los "handlers" puede tratar la excepcion, llega a la ultima, que es una llamada basicamente a (despues de salvar los registros en la pila, buscad a ver que hay en esa direccion con el olly, os encontrareis con muchos push registro) kernel32.UnHanded Exception Filter () (a filtro de excepciones no manejado) y luego a ntdll.ZwRaiseException, y basicamente, te sale el cuadrito de que se ha producido una excepcion blablabla y ExitProccess();
Al rollo

Si ejecutaramos de nuevo el programita de arriba, pasandole muchas AAAAs, pero antes de que "pete", meter un BP en la direccion que muestre el SE Handler de la pila (sera una direccion de kernel32.dll) y luego otro en kernel32.UnhandedExceptionFilter().
En mi caso (Win XP SP1) son respectivamente 77E7b2e5 y 77e79b95.
Al seguir con la ejecucion, os saltara aviso de excepcion y pulsais SHIFT + F9 (shift+f7 manda la excepcion al programa, en este caso es lo mismo porque el programa no tiene manejador de excepciones y la mandara respectivamente al sistema. shift+f9 manda la excepcion al sistema directamente, es decir, al ultimo SE Handler, el que todo thread iniciado en Windows tiene)
Entonces vereis que primero salta a 77e7b2e5 (el ultimo SEH que habia en la pila, el de sistema) y luego en 77e79b95, que es donde reside la funcion de Unhanded Exception Filter

Para que sirve todo esto? Bueno

Si le meteis tooodos estos argumentos al programa (arguments en el olly, reseteais, y lo ejecutais de nuevo con f9):
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Al ejecutarlo y copiar las AAAs al buffer, tenemos esto en la pila:
0022FFD4 41414141
0022FFD8 41414141
0022FFDC 41414141
0022FFE0 FFFFFF00 Pointer to next SEH record
0022FFE4 77E7B2E5 SE handler
0022FFE8 77E77CE0 kernel32.77E77CE0
El null que hay en el pointer se cuela ahi, no se porque xDD, pero no nos estorba para nada. Hemos metido tantas AAAs (y hemos sobreescrito un monton del stack) que hemos llegado a donde se guarda el SEH handler (en este caso, el unico, que es el que pone el sistema por defecto). Que pasa si lo sobreescribimos?? (el pointer se sobreescribe sin que importe)
Metemos el argumento anterior (AAAA....) mas 8 bytes mas (AAAA+BBBB):
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAA+BBBB (los "+" quitadlos, es para que veais como va el tema

)
Que ocurre? Se produce la excepcion (trata de ejecutar 41414141) y si le damos a shift f9 (repito, en este caso, saltara igual al SEH del sistema) y....
PREMIO!!!!!
Access violation when executing [42424242] - use Shift+F7/F8/F9) to pass exception to program
Trata de ejecutar BBBB, que es con lo que habiamos sobreescrito el SEH!!!!!
Tenemos el control absoluto del programa

Bueno, y todo este rollo, para que sirve? En el anterior buffer overflow, para nada, ya que con muchos menos bytes (simplemente sobreescribiendo el ret en la pila y apuntado a la shellcode) solucionabamos el problema.
Como ya he dicho, los programas "comerciales" se suelen meter manejadores de excepciones para tratar de "arreglar" el problema sin llegar a cerrar el programa. Esto se puede entender bien en el texto de Undersec (arriba del todo, textos), con el texto del exploit del WarFTP.
En el, se produce un stack overflow (EIP=41414141 en ese caso tambien al probarlo Eid0) pero el WarFTP tiene un manejador de excepciones que "soluciona" el problema, y al usuario no se le muestra NADA, es decir, el programa "arregla" el problema y parece que no ha pasado nada.
Esto mas o menos se hace (y es lo que interesa) metiendo en cada thread la direccion del siguiente SEH handler, asi como el manejador propio de ese thread, en la pila, como vimos arriba, donde los handlers van chaineados hasta el ultimo.
Bien, ahora imaginemos que tenemos el control de un registro en un overflow, pero, pero, el RET (la direccion de retorno) esta "muy abajo", y tenemos que sobreescribir demasiado, incluso funciones, valores o punteros que el programa necesita para llegar a ese RET y que tomemos el control del programa.
Si tenemos el control del registro ECX (por lo que sea, una variable, un POP ECX lo que sea) que se usa en una, por ejemplo, instruccion como esta
POP ECX
MOV EAX,DWORD PTR SS:[ECX+C]
.....
....
.....
(no hay call eax ni call ecx ni nada, no tenemos el control de la ejecucion del programa)
.....
Si metemos AAAAs... en ECX (porque antes ha habido por ejemplo un POP ECX), esta instruccion generara un error de lectura (fijo) al intentar leer AAB6 (osea, 41414206)que ademas no es de la pila.
Es decir, sabemos que hay un overflow ahi, lo controlamos, podemos sobreescribir variables en la pila hasta el final (algo exagerado, me refiero a que podemos sobreescribir variables en la pila, pero no tomar el control con un ret normal), pero no podemos dirigir la ejecucion del codigo a nuestra shellcode.
Pero, pero, si dicho thread en la pila tiene un SEH (un SEH local, por ejemplo, si se trata de una funcion que hace divisiones, el SEH puede tratar de manejar las divisones por 0, en vez de que lo haga el sistema, que acaba con un ExitProccess()), y lo podemos sobreescribir, tenemos el control absoluto del programa

Ejemplo de varios SEH en la pila:
007DF018 30343831
007DF01C 77C00031 msvcrt.77C00031
007DF020 007DF14C
007DF024 77C03EB0 msvcrt._except_handler3
007DF028 77BE2030 msvcrt.77BE2030
007DF02C FFFFFFFF
007DF030 77BFAB33 RETURN to msvcrt.77BFAB33 from msvcrt.77C054FD
007DF034 007DF064 Pointer to next SEH record
007DF038 0045CD5B SE handler
007DF03C 00000000
007DF040 0043F67A war-ftpd.00429490
007DF044 00AD9C8E
007DF048 007DF080
007DF04C 000003E8
007DF050 00477E18 war-ftpd.00477E18
007DF054 00000012
007DF058 00AD4370
007DF05C 00000271
007DF060 00000255
007DF064 007DF14C Pointer to next SEH record
007DF068 0045D588 SE handler
En muchos exploits se hace asi, sobre todo en los basados en servicios de Windows (buscadlos, casi siempre hay SEH overwritting

) Tambien fijaros en el paper de arriba de Practical-SEH-Exploitation donde se usa esto precisamente.
En el SEH sobreescrito, se puede meter de "todo", desde offsetsa DLLs a jmp esp o jmp ebp (salta al inicio del stack del thread,ESP, o al final, EBP), a offsets para sacar uno o varios valores de la pila con POPs (como el del SERVU) (tambien en DLLs, tienen que ser cargadas por el programa vulnerable) o incluso, un valor fijo de la pila (cosa que no funcionara en casi ningun sistema, pero....)
Bueno, trasteando con el tema, he aprendido bastante, era algo que no conocia

Espero que os sirva el texto, va dedicado a todos mis detractores

Espero que a gospel no le importe que le ponga una chincheta

(humildad? si soy perfecto!!!"

)
Ya en serio, espero que lo entendais, y que POR FAVOR, POR FAVOR, reportadme los errores (de buen rollo joder, no llamandome de todo), que soy muy muy novato en el tema, solo estoy probando cosas

Salu2